CrackMe.apk
Download file
package com.google.android.exoplayer2.extractor.ts;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.extractor.ExtractorOutput;
import com.google.android.exoplayer2.extractor.TrackOutput;
import com.google.android.exoplayer2.extractor.ts.TsPayloadReader;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.NalUnitUtil;
import com.google.android.exoplayer2.util.ParsableBitArray;
import com.google.android.exoplayer2.util.ParsableByteArray;
import com.google.android.exoplayer2.util.Util;
import java.util.Arrays;
import java.util.Collections;
public final class H263Reader implements ElementaryStreamReader {
private static final float[] PIXEL_WIDTH_HEIGHT_RATIO_BY_ASPECT_RATIO_INFO = {1.0f, 1.0f, 1.0909091f, 0.90909094f, 1.4545455f, 1.2121212f, 1.0f};
private static final int START_CODE_VALUE_GROUP_OF_VOP = 179;
private static final int START_CODE_VALUE_MAX_VIDEO_OBJECT = 31;
private static final int START_CODE_VALUE_UNSET = -1;
private static final int START_CODE_VALUE_USER_DATA = 178;
private static final int START_CODE_VALUE_VISUAL_OBJECT = 181;
private static final int START_CODE_VALUE_VISUAL_OBJECT_SEQUENCE = 176;
private static final int START_CODE_VALUE_VOP = 182;
private static final String TAG = "H263Reader";
private static final int VIDEO_OBJECT_LAYER_SHAPE_RECTANGULAR = 0;
private final CsdBuffer csdBuffer;
private String formatId;
private boolean hasOutputFormat;
private TrackOutput output;
private long pesTimeUs;
private final boolean[] prefixFlags;
private SampleReader sampleReader;
private long totalBytesWritten;
private final NalUnitTargetBuffer userData;
private final ParsableByteArray userDataParsable;
private final UserDataReader userDataReader;
public void packetFinished() {
}
public H263Reader() {
this((UserDataReader) null);
}
H263Reader(UserDataReader userDataReader2) {
this.userDataReader = userDataReader2;
this.prefixFlags = new boolean[4];
this.csdBuffer = new CsdBuffer(128);
this.pesTimeUs = C.TIME_UNSET;
if (userDataReader2 != null) {
this.userData = new NalUnitTargetBuffer(START_CODE_VALUE_USER_DATA, 128);
this.userDataParsable = new ParsableByteArray();
return;
}
this.userData = null;
this.userDataParsable = null;
}
public void seek() {
NalUnitUtil.clearPrefixFlags(this.prefixFlags);
this.csdBuffer.reset();
SampleReader sampleReader2 = this.sampleReader;
if (sampleReader2 != null) {
sampleReader2.reset();
}
NalUnitTargetBuffer nalUnitTargetBuffer = this.userData;
if (nalUnitTargetBuffer != null) {
nalUnitTargetBuffer.reset();
}
this.totalBytesWritten = 0;
this.pesTimeUs = C.TIME_UNSET;
}
public void createTracks(ExtractorOutput extractorOutput, TsPayloadReader.TrackIdGenerator trackIdGenerator) {
trackIdGenerator.generateNewId();
this.formatId = trackIdGenerator.getFormatId();
TrackOutput track = extractorOutput.track(trackIdGenerator.getTrackId(), 2);
this.output = track;
this.sampleReader = new SampleReader(track);
UserDataReader userDataReader2 = this.userDataReader;
if (userDataReader2 != null) {
userDataReader2.createTracks(extractorOutput, trackIdGenerator);
}
}
public void packetStarted(long j, int i) {
if (j != C.TIME_UNSET) {
this.pesTimeUs = j;
}
}
public void consume(ParsableByteArray parsableByteArray) {
Assertions.checkStateNotNull(this.sampleReader);
Assertions.checkStateNotNull(this.output);
int position = parsableByteArray.getPosition();
int limit = parsableByteArray.limit();
byte[] data = parsableByteArray.getData();
this.totalBytesWritten += (long) parsableByteArray.bytesLeft();
this.output.sampleData(parsableByteArray, parsableByteArray.bytesLeft());
while (true) {
int findNalUnit = NalUnitUtil.findNalUnit(data, position, limit, this.prefixFlags);
if (findNalUnit == limit) {
break;
}
int i = findNalUnit + 3;
byte b = parsableByteArray.getData()[i] & 255;
int i2 = findNalUnit - position;
int i3 = 0;
if (!this.hasOutputFormat) {
if (i2 > 0) {
this.csdBuffer.onData(data, position, findNalUnit);
}
if (this.csdBuffer.onStartCode(b, i2 < 0 ? -i2 : 0)) {
TrackOutput trackOutput = this.output;
CsdBuffer csdBuffer2 = this.csdBuffer;
trackOutput.format(parseCsdBuffer(csdBuffer2, csdBuffer2.volStartPosition, (String) Assertions.checkNotNull(this.formatId)));
this.hasOutputFormat = true;
}
}
this.sampleReader.onData(data, position, findNalUnit);
NalUnitTargetBuffer nalUnitTargetBuffer = this.userData;
if (nalUnitTargetBuffer != null) {
if (i2 > 0) {
nalUnitTargetBuffer.appendToNalUnit(data, position, findNalUnit);
} else {
i3 = -i2;
}
if (this.userData.endNalUnit(i3)) {
((ParsableByteArray) Util.castNonNull(this.userDataParsable)).reset(this.userData.nalData, NalUnitUtil.unescapeStream(this.userData.nalData, this.userData.nalLength));
((UserDataReader) Util.castNonNull(this.userDataReader)).consume(this.pesTimeUs, this.userDataParsable);
}
if (b == START_CODE_VALUE_USER_DATA && parsableByteArray.getData()[findNalUnit + 2] == 1) {
this.userData.startNalUnit(b);
}
}
int i4 = limit - findNalUnit;
this.sampleReader.onDataEnd(this.totalBytesWritten - ((long) i4), i4, this.hasOutputFormat);
this.sampleReader.onStartCode(b, this.pesTimeUs);
position = i;
}
if (!this.hasOutputFormat) {
this.csdBuffer.onData(data, position, limit);
}
this.sampleReader.onData(data, position, limit);
NalUnitTargetBuffer nalUnitTargetBuffer2 = this.userData;
if (nalUnitTargetBuffer2 != null) {
nalUnitTargetBuffer2.appendToNalUnit(data, position, limit);
}
}
private static Format parseCsdBuffer(CsdBuffer csdBuffer2, int i, String str) {
byte[] copyOf = Arrays.copyOf(csdBuffer2.data, csdBuffer2.length);
ParsableBitArray parsableBitArray = new ParsableBitArray(copyOf);
parsableBitArray.skipBytes(i);
parsableBitArray.skipBytes(4);
parsableBitArray.skipBit();
parsableBitArray.skipBits(8);
if (parsableBitArray.readBit()) {
parsableBitArray.skipBits(4);
parsableBitArray.skipBits(3);
}
int readBits = parsableBitArray.readBits(4);
float f = 1.0f;
if (readBits == 15) {
int readBits2 = parsableBitArray.readBits(8);
int readBits3 = parsableBitArray.readBits(8);
if (readBits3 == 0) {
Log.w(TAG, "Invalid aspect ratio");
} else {
f = ((float) readBits2) / ((float) readBits3);
}
} else {
float[] fArr = PIXEL_WIDTH_HEIGHT_RATIO_BY_ASPECT_RATIO_INFO;
if (readBits < fArr.length) {
f = fArr[readBits];
} else {
Log.w(TAG, "Invalid aspect ratio");
}
}
if (parsableBitArray.readBit()) {
parsableBitArray.skipBits(2);
parsableBitArray.skipBits(1);
if (parsableBitArray.readBit()) {
parsableBitArray.skipBits(15);
parsableBitArray.skipBit();
parsableBitArray.skipBits(15);
parsableBitArray.skipBit();
parsableBitArray.skipBits(15);
parsableBitArray.skipBit();
parsableBitArray.skipBits(3);
parsableBitArray.skipBits(11);
parsableBitArray.skipBit();
parsableBitArray.skipBits(15);
parsableBitArray.skipBit();
}
}
if (parsableBitArray.readBits(2) != 0) {
Log.w(TAG, "Unhandled video object layer shape");
}
parsableBitArray.skipBit();
int readBits4 = parsableBitArray.readBits(16);
parsableBitArray.skipBit();
if (parsableBitArray.readBit()) {
if (readBits4 == 0) {
Log.w(TAG, "Invalid vop_increment_time_resolution");
} else {
int i2 = 0;
for (int i3 = readBits4 - 1; i3 > 0; i3 >>= 1) {
i2++;
}
parsableBitArray.skipBits(i2);
}
}
parsableBitArray.skipBit();
int readBits5 = parsableBitArray.readBits(13);
parsableBitArray.skipBit();
int readBits6 = parsableBitArray.readBits(13);
parsableBitArray.skipBit();
parsableBitArray.skipBit();
return new Format.Builder().setId(str).setSampleMimeType(MimeTypes.VIDEO_MP4V).setWidth(readBits5).setHeight(readBits6).setPixelWidthHeightRatio(f).setInitializationData(Collections.singletonList(copyOf)).build();
}
private static final class CsdBuffer {
private static final byte[] START_CODE = {0, 0, 1};
private static final int STATE_EXPECT_VIDEO_OBJECT_LAYER_START = 3;
private static final int STATE_EXPECT_VIDEO_OBJECT_START = 2;
private static final int STATE_EXPECT_VISUAL_OBJECT_START = 1;
private static final int STATE_SKIP_TO_VISUAL_OBJECT_SEQUENCE_START = 0;
private static final int STATE_WAIT_FOR_VOP_START = 4;
public byte[] data;
private boolean isFilling;
public int length;
private int state;
public int volStartPosition;
public CsdBuffer(int i) {
this.data = new byte[i];
}
public void reset() {
this.isFilling = false;
this.length = 0;
this.state = 0;
}
public boolean onStartCode(int i, int i2) {
int i3 = this.state;
if (i3 != 0) {
if (i3 != 1) {
if (i3 != 2) {
if (i3 != 3) {
if (i3 != 4) {
throw new IllegalStateException();
} else if (i == H263Reader.START_CODE_VALUE_GROUP_OF_VOP || i == H263Reader.START_CODE_VALUE_VISUAL_OBJECT) {
this.length -= i2;
this.isFilling = false;
return true;
}
} else if ((i & PsExtractor.VIDEO_STREAM_MASK) != 32) {
Log.w(H263Reader.TAG, "Unexpected start code value");
reset();
} else {
this.volStartPosition = this.length;
this.state = 4;
}
} else if (i > 31) {
Log.w(H263Reader.TAG, "Unexpected start code value");
reset();
} else {
this.state = 3;
}
} else if (i != H263Reader.START_CODE_VALUE_VISUAL_OBJECT) {
Log.w(H263Reader.TAG, "Unexpected start code value");
reset();
} else {
this.state = 2;
}
} else if (i == H263Reader.START_CODE_VALUE_VISUAL_OBJECT_SEQUENCE) {
this.state = 1;
this.isFilling = true;
}
byte[] bArr = START_CODE;
onData(bArr, 0, bArr.length);
return false;
}
public void onData(byte[] bArr, int i, int i2) {
if (this.isFilling) {
int i3 = i2 - i;
byte[] bArr2 = this.data;
int length2 = bArr2.length;
int i4 = this.length;
if (length2 < i4 + i3) {
this.data = Arrays.copyOf(bArr2, (i4 + i3) * 2);
}
System.arraycopy(bArr, i, this.data, this.length, i3);
this.length += i3;
}
}
}
private static final class SampleReader {
private static final int OFFSET_VOP_CODING_TYPE = 1;
private static final int VOP_CODING_TYPE_INTRA = 0;
private boolean lookingForVopCodingType;
private final TrackOutput output;
private boolean readingSample;
private boolean sampleIsKeyframe;
private long samplePosition;
private long sampleTimeUs;
private int startCodeValue;
private int vopBytesRead;
public SampleReader(TrackOutput trackOutput) {
this.output = trackOutput;
}
public void reset() {
this.readingSample = false;
this.lookingForVopCodingType = false;
this.sampleIsKeyframe = false;
this.startCodeValue = -1;
}
public void onStartCode(int i, long j) {
this.startCodeValue = i;
this.sampleIsKeyframe = false;
boolean z = true;
this.readingSample = i == H263Reader.START_CODE_VALUE_VOP || i == H263Reader.START_CODE_VALUE_GROUP_OF_VOP;
if (i != H263Reader.START_CODE_VALUE_VOP) {
z = false;
}
this.lookingForVopCodingType = z;
this.vopBytesRead = 0;
this.sampleTimeUs = j;
}
public void onData(byte[] bArr, int i, int i2) {
if (this.lookingForVopCodingType) {
int i3 = this.vopBytesRead;
int i4 = (i + 1) - i3;
if (i4 < i2) {
this.sampleIsKeyframe = ((bArr[i4] & 192) >> 6) == 0;
this.lookingForVopCodingType = false;
return;
}
this.vopBytesRead = i3 + (i2 - i);
}
}
public void onDataEnd(long j, int i, boolean z) {
if (this.startCodeValue == H263Reader.START_CODE_VALUE_VOP && z && this.readingSample) {
long j2 = this.sampleTimeUs;
if (j2 != C.TIME_UNSET) {
int i2 = (int) (j - this.samplePosition);
this.output.sampleMetadata(j2, this.sampleIsKeyframe ? 1 : 0, i2, i, (TrackOutput.CryptoData) null);
}
}
if (this.startCodeValue != H263Reader.START_CODE_VALUE_GROUP_OF_VOP) {
this.samplePosition = j;
}
}
}
}
Download file