mirror of
https://github.com/Pinball3D/Rabbit-R1.git
synced 2024-12-27 09:32:27 -06:00
376 lines
14 KiB
Java
376 lines
14 KiB
Java
package androidx.media3.extractor.ts;
|
|
|
|
import androidx.media3.common.Format;
|
|
import androidx.media3.common.ParserException;
|
|
import androidx.media3.common.util.Assertions;
|
|
import androidx.media3.common.util.Log;
|
|
import androidx.media3.common.util.ParsableBitArray;
|
|
import androidx.media3.common.util.ParsableByteArray;
|
|
import androidx.media3.common.util.Util;
|
|
import androidx.media3.extractor.AacUtil;
|
|
import androidx.media3.extractor.DummyTrackOutput;
|
|
import androidx.media3.extractor.ExtractorOutput;
|
|
import androidx.media3.extractor.TrackOutput;
|
|
import androidx.media3.extractor.ts.TsPayloadReader;
|
|
import java.util.Arrays;
|
|
import java.util.Collections;
|
|
import org.checkerframework.checker.nullness.qual.EnsuresNonNull;
|
|
import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|
|
|
/* loaded from: classes2.dex */
|
|
public final class AdtsReader implements ElementaryStreamReader {
|
|
private static final int CRC_SIZE = 2;
|
|
private static final int HEADER_SIZE = 5;
|
|
private static final int ID3_HEADER_SIZE = 10;
|
|
private static final byte[] ID3_IDENTIFIER = {73, 68, 51};
|
|
private static final int ID3_SIZE_OFFSET = 6;
|
|
private static final int MATCH_STATE_FF = 512;
|
|
private static final int MATCH_STATE_I = 768;
|
|
private static final int MATCH_STATE_ID = 1024;
|
|
private static final int MATCH_STATE_START = 256;
|
|
private static final int MATCH_STATE_VALUE_SHIFT = 8;
|
|
private static final int STATE_CHECKING_ADTS_HEADER = 1;
|
|
private static final int STATE_FINDING_SAMPLE = 0;
|
|
private static final int STATE_READING_ADTS_HEADER = 3;
|
|
private static final int STATE_READING_ID3_HEADER = 2;
|
|
private static final int STATE_READING_SAMPLE = 4;
|
|
private static final String TAG = "AdtsReader";
|
|
private static final int VERSION_UNSET = -1;
|
|
private final ParsableBitArray adtsScratch;
|
|
private int bytesRead;
|
|
private int currentFrameVersion;
|
|
private TrackOutput currentOutput;
|
|
private long currentSampleDuration;
|
|
private final boolean exposeId3;
|
|
private int firstFrameSampleRateIndex;
|
|
private int firstFrameVersion;
|
|
private String formatId;
|
|
private boolean foundFirstFrame;
|
|
private boolean hasCrc;
|
|
private boolean hasOutputFormat;
|
|
private final ParsableByteArray id3HeaderBuffer;
|
|
private TrackOutput id3Output;
|
|
private final String language;
|
|
private int matchState;
|
|
private TrackOutput output;
|
|
private long sampleDurationUs;
|
|
private int sampleSize;
|
|
private int state;
|
|
private long timeUs;
|
|
|
|
public static boolean isAdtsSyncWord(int i) {
|
|
return (i & 65526) == 65520;
|
|
}
|
|
|
|
private void setCheckingAdtsHeaderState() {
|
|
this.state = 1;
|
|
this.bytesRead = 0;
|
|
}
|
|
|
|
private void setFindingSampleState() {
|
|
this.state = 0;
|
|
this.bytesRead = 0;
|
|
this.matchState = 256;
|
|
}
|
|
|
|
private void setReadingAdtsHeaderState() {
|
|
this.state = 3;
|
|
this.bytesRead = 0;
|
|
}
|
|
|
|
private void setReadingSampleState(TrackOutput trackOutput, long j, int i, int i2) {
|
|
this.state = 4;
|
|
this.bytesRead = i;
|
|
this.currentOutput = trackOutput;
|
|
this.currentSampleDuration = j;
|
|
this.sampleSize = i2;
|
|
}
|
|
|
|
public long getSampleDurationUs() {
|
|
return this.sampleDurationUs;
|
|
}
|
|
|
|
@Override // androidx.media3.extractor.ts.ElementaryStreamReader
|
|
public void packetFinished() {
|
|
}
|
|
|
|
@Override // androidx.media3.extractor.ts.ElementaryStreamReader
|
|
public void packetStarted(long j, int i) {
|
|
if (j != -9223372036854775807L) {
|
|
this.timeUs = j;
|
|
}
|
|
}
|
|
|
|
public AdtsReader(boolean z) {
|
|
this(z, null);
|
|
}
|
|
|
|
public AdtsReader(boolean z, String str) {
|
|
this.adtsScratch = new ParsableBitArray(new byte[7]);
|
|
this.id3HeaderBuffer = new ParsableByteArray(Arrays.copyOf(ID3_IDENTIFIER, 10));
|
|
setFindingSampleState();
|
|
this.firstFrameVersion = -1;
|
|
this.firstFrameSampleRateIndex = -1;
|
|
this.sampleDurationUs = -9223372036854775807L;
|
|
this.timeUs = -9223372036854775807L;
|
|
this.exposeId3 = z;
|
|
this.language = str;
|
|
}
|
|
|
|
@Override // androidx.media3.extractor.ts.ElementaryStreamReader
|
|
public void seek() {
|
|
this.timeUs = -9223372036854775807L;
|
|
resetSync();
|
|
}
|
|
|
|
@Override // androidx.media3.extractor.ts.ElementaryStreamReader
|
|
public void createTracks(ExtractorOutput extractorOutput, TsPayloadReader.TrackIdGenerator trackIdGenerator) {
|
|
trackIdGenerator.generateNewId();
|
|
this.formatId = trackIdGenerator.getFormatId();
|
|
TrackOutput track = extractorOutput.track(trackIdGenerator.getTrackId(), 1);
|
|
this.output = track;
|
|
this.currentOutput = track;
|
|
if (this.exposeId3) {
|
|
trackIdGenerator.generateNewId();
|
|
TrackOutput track2 = extractorOutput.track(trackIdGenerator.getTrackId(), 5);
|
|
this.id3Output = track2;
|
|
track2.format(new Format.Builder().setId(trackIdGenerator.getFormatId()).setSampleMimeType("application/id3").build());
|
|
return;
|
|
}
|
|
this.id3Output = new DummyTrackOutput();
|
|
}
|
|
|
|
@Override // androidx.media3.extractor.ts.ElementaryStreamReader
|
|
public void consume(ParsableByteArray parsableByteArray) throws ParserException {
|
|
assertTracksCreated();
|
|
while (parsableByteArray.bytesLeft() > 0) {
|
|
int i = this.state;
|
|
if (i == 0) {
|
|
findNextSample(parsableByteArray);
|
|
} else if (i == 1) {
|
|
checkAdtsHeader(parsableByteArray);
|
|
} else if (i != 2) {
|
|
if (i == 3) {
|
|
if (continueRead(parsableByteArray, this.adtsScratch.data, this.hasCrc ? 7 : 5)) {
|
|
parseAdtsHeader();
|
|
}
|
|
} else if (i == 4) {
|
|
readSample(parsableByteArray);
|
|
} else {
|
|
throw new IllegalStateException();
|
|
}
|
|
} else if (continueRead(parsableByteArray, this.id3HeaderBuffer.getData(), 10)) {
|
|
parseId3Header();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void resetSync() {
|
|
this.foundFirstFrame = false;
|
|
setFindingSampleState();
|
|
}
|
|
|
|
private boolean continueRead(ParsableByteArray parsableByteArray, byte[] bArr, int i) {
|
|
int min = Math.min(parsableByteArray.bytesLeft(), i - this.bytesRead);
|
|
parsableByteArray.readBytes(bArr, this.bytesRead, min);
|
|
int i2 = this.bytesRead + min;
|
|
this.bytesRead = i2;
|
|
return i2 == i;
|
|
}
|
|
|
|
private void setReadingId3HeaderState() {
|
|
this.state = 2;
|
|
this.bytesRead = ID3_IDENTIFIER.length;
|
|
this.sampleSize = 0;
|
|
this.id3HeaderBuffer.setPosition(0);
|
|
}
|
|
|
|
private void findNextSample(ParsableByteArray parsableByteArray) {
|
|
byte[] data = parsableByteArray.getData();
|
|
int position = parsableByteArray.getPosition();
|
|
int limit = parsableByteArray.limit();
|
|
while (position < limit) {
|
|
int i = position + 1;
|
|
byte b = data[position];
|
|
int i2 = b & 255;
|
|
if (this.matchState == 512 && isAdtsSyncBytes((byte) -1, (byte) i2) && (this.foundFirstFrame || checkSyncPositionValid(parsableByteArray, position - 1))) {
|
|
this.currentFrameVersion = (b & 8) >> 3;
|
|
this.hasCrc = (b & 1) == 0;
|
|
if (!this.foundFirstFrame) {
|
|
setCheckingAdtsHeaderState();
|
|
} else {
|
|
setReadingAdtsHeaderState();
|
|
}
|
|
parsableByteArray.setPosition(i);
|
|
return;
|
|
}
|
|
int i3 = this.matchState;
|
|
int i4 = i2 | i3;
|
|
if (i4 == 329) {
|
|
this.matchState = 768;
|
|
} else if (i4 == 511) {
|
|
this.matchState = 512;
|
|
} else if (i4 == 836) {
|
|
this.matchState = 1024;
|
|
} else if (i4 == 1075) {
|
|
setReadingId3HeaderState();
|
|
parsableByteArray.setPosition(i);
|
|
return;
|
|
} else if (i3 != 256) {
|
|
this.matchState = 256;
|
|
}
|
|
position = i;
|
|
}
|
|
parsableByteArray.setPosition(position);
|
|
}
|
|
|
|
private void checkAdtsHeader(ParsableByteArray parsableByteArray) {
|
|
if (parsableByteArray.bytesLeft() == 0) {
|
|
return;
|
|
}
|
|
this.adtsScratch.data[0] = parsableByteArray.getData()[parsableByteArray.getPosition()];
|
|
this.adtsScratch.setPosition(2);
|
|
int readBits = this.adtsScratch.readBits(4);
|
|
int i = this.firstFrameSampleRateIndex;
|
|
if (i != -1 && readBits != i) {
|
|
resetSync();
|
|
return;
|
|
}
|
|
if (!this.foundFirstFrame) {
|
|
this.foundFirstFrame = true;
|
|
this.firstFrameVersion = this.currentFrameVersion;
|
|
this.firstFrameSampleRateIndex = readBits;
|
|
}
|
|
setReadingAdtsHeaderState();
|
|
}
|
|
|
|
private boolean checkSyncPositionValid(ParsableByteArray parsableByteArray, int i) {
|
|
parsableByteArray.setPosition(i + 1);
|
|
if (!tryRead(parsableByteArray, this.adtsScratch.data, 1)) {
|
|
return false;
|
|
}
|
|
this.adtsScratch.setPosition(4);
|
|
int readBits = this.adtsScratch.readBits(1);
|
|
int i2 = this.firstFrameVersion;
|
|
if (i2 != -1 && readBits != i2) {
|
|
return false;
|
|
}
|
|
if (this.firstFrameSampleRateIndex != -1) {
|
|
if (!tryRead(parsableByteArray, this.adtsScratch.data, 1)) {
|
|
return true;
|
|
}
|
|
this.adtsScratch.setPosition(2);
|
|
if (this.adtsScratch.readBits(4) != this.firstFrameSampleRateIndex) {
|
|
return false;
|
|
}
|
|
parsableByteArray.setPosition(i + 2);
|
|
}
|
|
if (!tryRead(parsableByteArray, this.adtsScratch.data, 4)) {
|
|
return true;
|
|
}
|
|
this.adtsScratch.setPosition(14);
|
|
int readBits2 = this.adtsScratch.readBits(13);
|
|
if (readBits2 < 7) {
|
|
return false;
|
|
}
|
|
byte[] data = parsableByteArray.getData();
|
|
int limit = parsableByteArray.limit();
|
|
int i3 = i + readBits2;
|
|
if (i3 >= limit) {
|
|
return true;
|
|
}
|
|
byte b = data[i3];
|
|
if (b == -1) {
|
|
int i4 = i3 + 1;
|
|
if (i4 == limit) {
|
|
return true;
|
|
}
|
|
return isAdtsSyncBytes((byte) -1, data[i4]) && ((data[i4] & 8) >> 3) == readBits;
|
|
}
|
|
if (b != 73) {
|
|
return false;
|
|
}
|
|
int i5 = i3 + 1;
|
|
if (i5 == limit) {
|
|
return true;
|
|
}
|
|
if (data[i5] != 68) {
|
|
return false;
|
|
}
|
|
int i6 = i3 + 2;
|
|
return i6 == limit || data[i6] == 51;
|
|
}
|
|
|
|
private boolean isAdtsSyncBytes(byte b, byte b2) {
|
|
return isAdtsSyncWord(((b & 255) << 8) | (b2 & 255));
|
|
}
|
|
|
|
private boolean tryRead(ParsableByteArray parsableByteArray, byte[] bArr, int i) {
|
|
if (parsableByteArray.bytesLeft() < i) {
|
|
return false;
|
|
}
|
|
parsableByteArray.readBytes(bArr, 0, i);
|
|
return true;
|
|
}
|
|
|
|
@RequiresNonNull({"id3Output"})
|
|
private void parseId3Header() {
|
|
this.id3Output.sampleData(this.id3HeaderBuffer, 10);
|
|
this.id3HeaderBuffer.setPosition(6);
|
|
setReadingSampleState(this.id3Output, 0L, 10, this.id3HeaderBuffer.readSynchSafeInt() + 10);
|
|
}
|
|
|
|
@RequiresNonNull({"output"})
|
|
private void parseAdtsHeader() throws ParserException {
|
|
this.adtsScratch.setPosition(0);
|
|
if (!this.hasOutputFormat) {
|
|
int i = 2;
|
|
int readBits = this.adtsScratch.readBits(2) + 1;
|
|
if (readBits != 2) {
|
|
Log.w(TAG, "Detected audio object type: " + readBits + ", but assuming AAC LC.");
|
|
} else {
|
|
i = readBits;
|
|
}
|
|
this.adtsScratch.skipBits(5);
|
|
byte[] buildAudioSpecificConfig = AacUtil.buildAudioSpecificConfig(i, this.firstFrameSampleRateIndex, this.adtsScratch.readBits(3));
|
|
AacUtil.Config parseAudioSpecificConfig = AacUtil.parseAudioSpecificConfig(buildAudioSpecificConfig);
|
|
Format build = new Format.Builder().setId(this.formatId).setSampleMimeType("audio/mp4a-latm").setCodecs(parseAudioSpecificConfig.codecs).setChannelCount(parseAudioSpecificConfig.channelCount).setSampleRate(parseAudioSpecificConfig.sampleRateHz).setInitializationData(Collections.singletonList(buildAudioSpecificConfig)).setLanguage(this.language).build();
|
|
this.sampleDurationUs = 1024000000 / build.sampleRate;
|
|
this.output.format(build);
|
|
this.hasOutputFormat = true;
|
|
} else {
|
|
this.adtsScratch.skipBits(10);
|
|
}
|
|
this.adtsScratch.skipBits(4);
|
|
int readBits2 = this.adtsScratch.readBits(13);
|
|
int i2 = readBits2 - 7;
|
|
if (this.hasCrc) {
|
|
i2 = readBits2 - 9;
|
|
}
|
|
setReadingSampleState(this.output, this.sampleDurationUs, 0, i2);
|
|
}
|
|
|
|
@RequiresNonNull({"currentOutput"})
|
|
private void readSample(ParsableByteArray parsableByteArray) {
|
|
int min = Math.min(parsableByteArray.bytesLeft(), this.sampleSize - this.bytesRead);
|
|
this.currentOutput.sampleData(parsableByteArray, min);
|
|
int i = this.bytesRead + min;
|
|
this.bytesRead = i;
|
|
int i2 = this.sampleSize;
|
|
if (i == i2) {
|
|
long j = this.timeUs;
|
|
if (j != -9223372036854775807L) {
|
|
this.currentOutput.sampleMetadata(j, 1, i2, 0, null);
|
|
this.timeUs += this.currentSampleDuration;
|
|
}
|
|
setFindingSampleState();
|
|
}
|
|
}
|
|
|
|
@EnsuresNonNull({"output", "currentOutput", "id3Output"})
|
|
private void assertTracksCreated() {
|
|
Assertions.checkNotNull(this.output);
|
|
Util.castNonNull(this.currentOutput);
|
|
Util.castNonNull(this.id3Output);
|
|
}
|
|
}
|