Improve AdtsExtractor#sniff when trying different sync word offsets

The previous implementation did the following (after skipping any ID3
headers at the start of the stream):
1. Skip forward byte-by-byte looking for a sync word (0xFFF)
2. Assume this indicates the start of an ADTS frame and read the size
  a) If frameSize <= 6 immediately return false
3. Skip forward by frameSize and expect to find another ADTS sync word
   (with no further scanning).
   b) If we find one, great! Loop from step 2.
   a) If we don't find one then assume the **last** sync word we found
      wasn't actually one, so loop from step 1 starting one extra byte
      into the stream. This means we're looking for a sync word we would
      have skipped over in step 3.

The asymmetry here comes from the different handling of frameSize <= 6
(immediately return false) and frameSize being 'wrong because it doesn't
lead to another sync word' (scan the file again from the beginning for
alternative sync words).

With this change both these cases are handled symmetrically (always scan
for alternative sync words). Step 2a) becomes the same as 3b): Loop back
to the beginning of the stream with an incremented offset and scan for
another sync word.

#minor-release

PiperOrigin-RevId: 397285756
This commit is contained in:
ibaker 2021-09-17 11:55:01 +01:00 committed by Christos Tsilopoulos
parent 6f728a43ad
commit 73aece6356

View File

@ -149,12 +149,12 @@ public final class AdtsExtractor implements Extractor {
scratch.setPosition(0);
int syncBytes = scratch.readUnsignedShort();
if (!AdtsReader.isAdtsSyncWord(syncBytes)) {
// We didn't find an ADTS sync word. Start searching again from one byte further into the
// start of the stream.
validFramesCount = 0;
totalValidFramesSize = 0;
headerPosition++;
input.resetPeekPosition();
if (++headerPosition - startPosition >= MAX_SNIFF_BYTES) {
return false;
}
input.advancePeekPosition(headerPosition);
} else {
if (++validFramesCount >= 4 && totalValidFramesSize > TsExtractor.TS_PACKET_SIZE) {
@ -165,12 +165,21 @@ public final class AdtsExtractor implements Extractor {
input.peekFully(scratch.getData(), 0, 4);
scratchBits.setPosition(14);
int frameSize = scratchBits.readBits(13);
// Either the stream is malformed OR we're not parsing an ADTS stream.
if (frameSize <= 6) {
return false;
// The size is too small, so we're probably not reading an ADTS frame. Start searching
// again from one byte further into the start of the stream.
validFramesCount = 0;
totalValidFramesSize = 0;
headerPosition++;
input.resetPeekPosition();
input.advancePeekPosition(headerPosition);
} else {
input.advancePeekPosition(frameSize - 6);
totalValidFramesSize += frameSize;
}
input.advancePeekPosition(frameSize - 6);
totalValidFramesSize += frameSize;
}
if (headerPosition - startPosition >= MAX_SNIFF_BYTES) {
return false;
}
}
}