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 {
@Mode private final int mode;
private final List<TimestampAdjuster> timestampAdjusters;
private final ParsableByteArray tsPacketBuffer;
private final ParsableBitArray tsScratch;
private final SparseIntArray continuityCounters;
private final TsPayloadReader.Factory payloadReaderFactory;
private final SparseArray<TsPayloadReader> tsPayloadReaders; // Indexed by pid
......@@ -164,7 +163,6 @@ public final class TsExtractor implements Extractor {
timestampAdjusters.add(timestampAdjuster);
}
tsPacketBuffer = new ParsableByteArray(BUFFER_SIZE);
tsScratch = new ParsableBitArray(new byte[3]);
trackIds = new SparseBooleanArray();
tsPayloadReaders = new SparseArray<>();
continuityCounters = new SparseIntArray();
......@@ -250,24 +248,23 @@ public final class TsExtractor implements Extractor {
return RESULT_CONTINUE;
}
tsPacketBuffer.skipBytes(1);
tsPacketBuffer.readBytes(tsScratch, 3);
if (tsScratch.readBit()) { // transport_error_indicator
int tsPacketHeader = tsPacketBuffer.readInt();
if ((tsPacketHeader & 0x800000) != 0) { // transport_error_indicator
// There are uncorrectable errors in this packet.
tsPacketBuffer.setPosition(endOfPacket);
return RESULT_CONTINUE;
}
boolean payloadUnitStartIndicator = tsScratch.readBit();
tsScratch.skipBits(1); // transport_priority
int pid = tsScratch.readBits(13);
tsScratch.skipBits(2); // transport_scrambling_control
boolean adaptationFieldExists = tsScratch.readBit();
boolean payloadExists = tsScratch.readBit();
boolean payloadUnitStartIndicator = (tsPacketHeader & 0x400000) != 0;
// Ignoring transport_priority (tsPacketHeader & 0x200000)
int pid = (tsPacketHeader & 0x1FFF00) >> 8;
// Ignoring transport_scrambling_control (tsPacketHeader & 0xC0)
boolean adaptationFieldExists = (tsPacketHeader & 0x20) != 0;
boolean payloadExists = (tsPacketHeader & 0x10) != 0;
// Discontinuity check.
boolean discontinuityFound = false;
int continuityCounter = tsScratch.readBits(4);
if (mode != MODE_HLS) {
int continuityCounter = tsPacketHeader & 0xF;
int previousCounter = continuityCounters.get(pid, continuityCounter - 1);
continuityCounters.put(pid, continuityCounter);
if (previousCounter == continuityCounter) {
......@@ -276,7 +273,7 @@ public final class TsExtractor implements Extractor {
tsPacketBuffer.setPosition(endOfPacket);
return RESULT_CONTINUE;
}
} else if (continuityCounter != (previousCounter + 1) % 16) {
} else if (continuityCounter != ((previousCounter + 1) & 0xF)) {
discontinuityFound = true;
}
}
......@@ -296,7 +293,6 @@ public final class TsExtractor implements Extractor {
}
tsPacketBuffer.setLimit(endOfPacket);
payloadReader.consume(tsPacketBuffer, payloadUnitStartIndicator);
Assertions.checkState(tsPacketBuffer.getPosition() <= endOfPacket);
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