CrackMe.apk
Download file
package com.google.android.exoplayer2.extractor.amr;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.ParserException;
import com.google.android.exoplayer2.audio.SilenceSkippingAudioProcessor;
import com.google.android.exoplayer2.extractor.ConstantBitrateSeekMap;
import com.google.android.exoplayer2.extractor.Extractor;
import com.google.android.exoplayer2.extractor.ExtractorInput;
import com.google.android.exoplayer2.extractor.ExtractorOutput;
import com.google.android.exoplayer2.extractor.ExtractorsFactory;
import com.google.android.exoplayer2.extractor.PositionHolder;
import com.google.android.exoplayer2.extractor.SeekMap;
import com.google.android.exoplayer2.extractor.TrackOutput;
import com.google.android.exoplayer2.upstream.DataReader;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.Util;
import java.io.EOFException;
import java.io.IOException;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Arrays;
import org.checkerframework.checker.nullness.qual.EnsuresNonNull;
import org.checkerframework.checker.nullness.qual.RequiresNonNull;
public final class AmrExtractor implements Extractor {
public static final ExtractorsFactory FACTORY = AmrExtractor$$ExternalSyntheticLambda0.INSTANCE;
public static final int FLAG_ENABLE_CONSTANT_BITRATE_SEEKING = 1;
public static final int FLAG_ENABLE_CONSTANT_BITRATE_SEEKING_ALWAYS = 2;
private static final int MAX_FRAME_SIZE_BYTES;
private static final int NUM_SAME_SIZE_CONSTANT_BIT_RATE_THRESHOLD = 20;
private static final int SAMPLE_RATE_NB = 8000;
private static final int SAMPLE_RATE_WB = 16000;
private static final int SAMPLE_TIME_PER_FRAME_US = 20000;
private static final byte[] amrSignatureNb = Util.getUtf8Bytes("#!AMR\n");
private static final byte[] amrSignatureWb = Util.getUtf8Bytes("#!AMR-WB\n");
private static final int[] frameSizeBytesByTypeNb = {13, 14, 16, 18, 20, 21, 27, 32, 6, 7, 6, 6, 1, 1, 1, 1};
private static final int[] frameSizeBytesByTypeWb;
private int currentSampleBytesRemaining;
private int currentSampleSize;
private long currentSampleTimeUs;
private ExtractorOutput extractorOutput;
private long firstSamplePosition;
private int firstSampleSize;
private final int flags;
private boolean hasOutputFormat;
private boolean hasOutputSeekMap;
private boolean isWideBand;
private int numSamplesWithSameSize;
private final byte[] scratch;
private SeekMap seekMap;
private long timeOffsetUs;
private TrackOutput trackOutput;
@Documented
@Target({ElementType.TYPE_USE})
@Retention(RetentionPolicy.SOURCE)
public @interface Flags {
}
public void release() {
}
static {
int[] iArr = {18, 24, 33, 37, 41, 47, 51, 59, 61, 6, 1, 1, 1, 1, 1, 1};
frameSizeBytesByTypeWb = iArr;
MAX_FRAME_SIZE_BYTES = iArr[8];
}
static /* synthetic */ Extractor[] lambda$static$0() {
return new Extractor[]{new AmrExtractor()};
}
public AmrExtractor() {
this(0);
}
public AmrExtractor(int i) {
this.flags = (i & 2) != 0 ? i | 1 : i;
this.scratch = new byte[1];
this.firstSampleSize = -1;
}
public boolean sniff(ExtractorInput extractorInput) throws IOException {
return readAmrHeader(extractorInput);
}
public void init(ExtractorOutput extractorOutput2) {
this.extractorOutput = extractorOutput2;
this.trackOutput = extractorOutput2.track(0, 1);
extractorOutput2.endTracks();
}
public int read(ExtractorInput extractorInput, PositionHolder positionHolder) throws IOException {
assertInitialized();
if (extractorInput.getPosition() != 0 || readAmrHeader(extractorInput)) {
maybeOutputFormat();
int readSample = readSample(extractorInput);
maybeOutputSeekMap(extractorInput.getLength(), readSample);
return readSample;
}
throw ParserException.createForMalformedContainer("Could not find AMR header.", (Throwable) null);
}
public void seek(long j, long j2) {
this.currentSampleTimeUs = 0;
this.currentSampleSize = 0;
this.currentSampleBytesRemaining = 0;
if (j != 0) {
SeekMap seekMap2 = this.seekMap;
if (seekMap2 instanceof ConstantBitrateSeekMap) {
this.timeOffsetUs = ((ConstantBitrateSeekMap) seekMap2).getTimeUsAtPosition(j);
return;
}
}
this.timeOffsetUs = 0;
}
static int frameSizeBytesByTypeNb(int i) {
return frameSizeBytesByTypeNb[i];
}
static int frameSizeBytesByTypeWb(int i) {
return frameSizeBytesByTypeWb[i];
}
static byte[] amrSignatureNb() {
byte[] bArr = amrSignatureNb;
return Arrays.copyOf(bArr, bArr.length);
}
static byte[] amrSignatureWb() {
byte[] bArr = amrSignatureWb;
return Arrays.copyOf(bArr, bArr.length);
}
private boolean readAmrHeader(ExtractorInput extractorInput) throws IOException {
byte[] bArr = amrSignatureNb;
if (peekAmrSignature(extractorInput, bArr)) {
this.isWideBand = false;
extractorInput.skipFully(bArr.length);
return true;
}
byte[] bArr2 = amrSignatureWb;
if (!peekAmrSignature(extractorInput, bArr2)) {
return false;
}
this.isWideBand = true;
extractorInput.skipFully(bArr2.length);
return true;
}
private static boolean peekAmrSignature(ExtractorInput extractorInput, byte[] bArr) throws IOException {
extractorInput.resetPeekPosition();
byte[] bArr2 = new byte[bArr.length];
extractorInput.peekFully(bArr2, 0, bArr.length);
return Arrays.equals(bArr2, bArr);
}
@RequiresNonNull({"trackOutput"})
private void maybeOutputFormat() {
if (!this.hasOutputFormat) {
this.hasOutputFormat = true;
boolean z = this.isWideBand;
this.trackOutput.format(new Format.Builder().setSampleMimeType(z ? MimeTypes.AUDIO_AMR_WB : MimeTypes.AUDIO_AMR_NB).setMaxInputSize(MAX_FRAME_SIZE_BYTES).setChannelCount(1).setSampleRate(z ? 16000 : 8000).build());
}
}
@RequiresNonNull({"trackOutput"})
private int readSample(ExtractorInput extractorInput) throws IOException {
if (this.currentSampleBytesRemaining == 0) {
try {
int peekNextSampleSize = peekNextSampleSize(extractorInput);
this.currentSampleSize = peekNextSampleSize;
this.currentSampleBytesRemaining = peekNextSampleSize;
if (this.firstSampleSize == -1) {
this.firstSamplePosition = extractorInput.getPosition();
this.firstSampleSize = this.currentSampleSize;
}
if (this.firstSampleSize == this.currentSampleSize) {
this.numSamplesWithSameSize++;
}
} catch (EOFException unused) {
return -1;
}
}
int sampleData = this.trackOutput.sampleData((DataReader) extractorInput, this.currentSampleBytesRemaining, true);
if (sampleData == -1) {
return -1;
}
int i = this.currentSampleBytesRemaining - sampleData;
this.currentSampleBytesRemaining = i;
if (i > 0) {
return 0;
}
this.trackOutput.sampleMetadata(this.timeOffsetUs + this.currentSampleTimeUs, 1, this.currentSampleSize, 0, (TrackOutput.CryptoData) null);
this.currentSampleTimeUs += SilenceSkippingAudioProcessor.DEFAULT_PADDING_SILENCE_US;
return 0;
}
private int peekNextSampleSize(ExtractorInput extractorInput) throws IOException {
extractorInput.resetPeekPosition();
extractorInput.peekFully(this.scratch, 0, 1);
byte b = this.scratch[0];
if ((b & 131) <= 0) {
return getFrameSizeInBytes((b >> 3) & 15);
}
throw ParserException.createForMalformedContainer("Invalid padding bits for frame header " + b, (Throwable) null);
}
private int getFrameSizeInBytes(int i) throws ParserException {
if (isValidFrameType(i)) {
return this.isWideBand ? frameSizeBytesByTypeWb[i] : frameSizeBytesByTypeNb[i];
}
StringBuilder sb = new StringBuilder();
sb.append("Illegal AMR ");
sb.append(this.isWideBand ? "WB" : "NB");
sb.append(" frame type ");
sb.append(i);
throw ParserException.createForMalformedContainer(sb.toString(), (Throwable) null);
}
private boolean isValidFrameType(int i) {
return i >= 0 && i <= 15 && (isWideBandValidFrameType(i) || isNarrowBandValidFrameType(i));
}
private boolean isWideBandValidFrameType(int i) {
return this.isWideBand && (i < 10 || i > 13);
}
private boolean isNarrowBandValidFrameType(int i) {
return !this.isWideBand && (i < 12 || i > 14);
}
@RequiresNonNull({"extractorOutput"})
private void maybeOutputSeekMap(long j, int i) {
int i2;
if (!this.hasOutputSeekMap) {
int i3 = this.flags;
if ((i3 & 1) == 0 || j == -1 || !((i2 = this.firstSampleSize) == -1 || i2 == this.currentSampleSize)) {
SeekMap.Unseekable unseekable = new SeekMap.Unseekable(C.TIME_UNSET);
this.seekMap = unseekable;
this.extractorOutput.seekMap(unseekable);
this.hasOutputSeekMap = true;
} else if (this.numSamplesWithSameSize >= 20 || i == -1) {
SeekMap constantBitrateSeekMap = getConstantBitrateSeekMap(j, (i3 & 2) != 0);
this.seekMap = constantBitrateSeekMap;
this.extractorOutput.seekMap(constantBitrateSeekMap);
this.hasOutputSeekMap = true;
}
}
}
private SeekMap getConstantBitrateSeekMap(long j, boolean z) {
return new ConstantBitrateSeekMap(j, this.firstSamplePosition, getBitrateFromFrameSize(this.firstSampleSize, SilenceSkippingAudioProcessor.DEFAULT_PADDING_SILENCE_US), this.firstSampleSize, z);
}
@EnsuresNonNull({"extractorOutput", "trackOutput"})
private void assertInitialized() {
Assertions.checkStateNotNull(this.trackOutput);
Util.castNonNull(this.extractorOutput);
}
private static int getBitrateFromFrameSize(int i, long j) {
return (int) (((((long) i) * 8) * 1000000) / j);
}
}
Download file