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.CodecSpecificDataUtil;
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.ParsableByteArray;
import com.google.android.exoplayer2.util.ParsableNalUnitBitArray;
import com.google.android.exoplayer2.util.Util;
import java.util.Collections;
import org.checkerframework.checker.nullness.qual.EnsuresNonNull;
import org.checkerframework.checker.nullness.qual.RequiresNonNull;
public final class H265Reader implements ElementaryStreamReader {
private static final int AUD_NUT = 35;
private static final int BLA_W_LP = 16;
private static final int CRA_NUT = 21;
private static final int PPS_NUT = 34;
private static final int PREFIX_SEI_NUT = 39;
private static final int RASL_R = 9;
private static final int SPS_NUT = 33;
private static final int SUFFIX_SEI_NUT = 40;
private static final String TAG = "H265Reader";
private static final int VPS_NUT = 32;
private String formatId;
private boolean hasOutputFormat;
private TrackOutput output;
private long pesTimeUs = C.TIME_UNSET;
private final NalUnitTargetBuffer pps = new NalUnitTargetBuffer(34, 128);
private final boolean[] prefixFlags = new boolean[3];
private final NalUnitTargetBuffer prefixSei = new NalUnitTargetBuffer(39, 128);
private SampleReader sampleReader;
private final SeiReader seiReader;
private final ParsableByteArray seiWrapper = new ParsableByteArray();
private final NalUnitTargetBuffer sps = new NalUnitTargetBuffer(33, 128);
private final NalUnitTargetBuffer suffixSei = new NalUnitTargetBuffer(40, 128);
private long totalBytesWritten;
private final NalUnitTargetBuffer vps = new NalUnitTargetBuffer(32, 128);
public void packetFinished() {
}
public H265Reader(SeiReader seiReader2) {
this.seiReader = seiReader2;
}
public void seek() {
this.totalBytesWritten = 0;
this.pesTimeUs = C.TIME_UNSET;
NalUnitUtil.clearPrefixFlags(this.prefixFlags);
this.vps.reset();
this.sps.reset();
this.pps.reset();
this.prefixSei.reset();
this.suffixSei.reset();
SampleReader sampleReader2 = this.sampleReader;
if (sampleReader2 != null) {
sampleReader2.reset();
}
}
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);
this.seiReader.createTracks(extractorOutput, trackIdGenerator);
}
public void packetStarted(long j, int i) {
if (j != C.TIME_UNSET) {
this.pesTimeUs = j;
}
}
public void consume(ParsableByteArray parsableByteArray) {
assertTracksCreated();
while (parsableByteArray.bytesLeft() > 0) {
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) {
if (position < limit) {
int findNalUnit = NalUnitUtil.findNalUnit(data, position, limit, this.prefixFlags);
if (findNalUnit == limit) {
nalUnitData(data, position, limit);
return;
}
int h265NalUnitType = NalUnitUtil.getH265NalUnitType(data, findNalUnit);
int i = findNalUnit - position;
if (i > 0) {
nalUnitData(data, position, findNalUnit);
}
int i2 = limit - findNalUnit;
long j = this.totalBytesWritten - ((long) i2);
int i3 = i < 0 ? -i : 0;
long j2 = j;
int i4 = i2;
endNalUnit(j2, i4, i3, this.pesTimeUs);
startNalUnit(j2, i4, h265NalUnitType, this.pesTimeUs);
position = findNalUnit + 3;
}
}
}
}
@RequiresNonNull({"sampleReader"})
private void startNalUnit(long j, int i, int i2, long j2) {
this.sampleReader.startNalUnit(j, i, i2, j2, this.hasOutputFormat);
if (!this.hasOutputFormat) {
this.vps.startNalUnit(i2);
this.sps.startNalUnit(i2);
this.pps.startNalUnit(i2);
}
this.prefixSei.startNalUnit(i2);
this.suffixSei.startNalUnit(i2);
}
@RequiresNonNull({"sampleReader"})
private void nalUnitData(byte[] bArr, int i, int i2) {
this.sampleReader.readNalUnitData(bArr, i, i2);
if (!this.hasOutputFormat) {
this.vps.appendToNalUnit(bArr, i, i2);
this.sps.appendToNalUnit(bArr, i, i2);
this.pps.appendToNalUnit(bArr, i, i2);
}
this.prefixSei.appendToNalUnit(bArr, i, i2);
this.suffixSei.appendToNalUnit(bArr, i, i2);
}
@RequiresNonNull({"output", "sampleReader"})
private void endNalUnit(long j, int i, int i2, long j2) {
this.sampleReader.endNalUnit(j, i, this.hasOutputFormat);
if (!this.hasOutputFormat) {
this.vps.endNalUnit(i2);
this.sps.endNalUnit(i2);
this.pps.endNalUnit(i2);
if (this.vps.isCompleted() && this.sps.isCompleted() && this.pps.isCompleted()) {
this.output.format(parseMediaFormat(this.formatId, this.vps, this.sps, this.pps));
this.hasOutputFormat = true;
}
}
if (this.prefixSei.endNalUnit(i2)) {
this.seiWrapper.reset(this.prefixSei.nalData, NalUnitUtil.unescapeStream(this.prefixSei.nalData, this.prefixSei.nalLength));
this.seiWrapper.skipBytes(5);
this.seiReader.consume(j2, this.seiWrapper);
}
if (this.suffixSei.endNalUnit(i2)) {
this.seiWrapper.reset(this.suffixSei.nalData, NalUnitUtil.unescapeStream(this.suffixSei.nalData, this.suffixSei.nalLength));
this.seiWrapper.skipBytes(5);
this.seiReader.consume(j2, this.seiWrapper);
}
}
private static Format parseMediaFormat(String str, NalUnitTargetBuffer nalUnitTargetBuffer, NalUnitTargetBuffer nalUnitTargetBuffer2, NalUnitTargetBuffer nalUnitTargetBuffer3) {
NalUnitTargetBuffer nalUnitTargetBuffer4 = nalUnitTargetBuffer;
NalUnitTargetBuffer nalUnitTargetBuffer5 = nalUnitTargetBuffer2;
NalUnitTargetBuffer nalUnitTargetBuffer6 = nalUnitTargetBuffer3;
byte[] bArr = new byte[(nalUnitTargetBuffer4.nalLength + nalUnitTargetBuffer5.nalLength + nalUnitTargetBuffer6.nalLength)];
System.arraycopy(nalUnitTargetBuffer4.nalData, 0, bArr, 0, nalUnitTargetBuffer4.nalLength);
System.arraycopy(nalUnitTargetBuffer5.nalData, 0, bArr, nalUnitTargetBuffer4.nalLength, nalUnitTargetBuffer5.nalLength);
System.arraycopy(nalUnitTargetBuffer6.nalData, 0, bArr, nalUnitTargetBuffer4.nalLength + nalUnitTargetBuffer5.nalLength, nalUnitTargetBuffer6.nalLength);
ParsableNalUnitBitArray parsableNalUnitBitArray = new ParsableNalUnitBitArray(nalUnitTargetBuffer5.nalData, 0, nalUnitTargetBuffer5.nalLength);
parsableNalUnitBitArray.skipBits(44);
int readBits = parsableNalUnitBitArray.readBits(3);
parsableNalUnitBitArray.skipBit();
int readBits2 = parsableNalUnitBitArray.readBits(2);
boolean readBit = parsableNalUnitBitArray.readBit();
int readBits3 = parsableNalUnitBitArray.readBits(5);
int i = 0;
for (int i2 = 0; i2 < 32; i2++) {
if (parsableNalUnitBitArray.readBit()) {
i |= 1 << i2;
}
}
int[] iArr = new int[6];
for (int i3 = 0; i3 < 6; i3++) {
iArr[i3] = parsableNalUnitBitArray.readBits(8);
}
int readBits4 = parsableNalUnitBitArray.readBits(8);
int i4 = 0;
for (int i5 = 0; i5 < readBits; i5++) {
if (parsableNalUnitBitArray.readBit()) {
i4 += 89;
}
if (parsableNalUnitBitArray.readBit()) {
i4 += 8;
}
}
parsableNalUnitBitArray.skipBits(i4);
if (readBits > 0) {
parsableNalUnitBitArray.skipBits((8 - readBits) * 2);
}
parsableNalUnitBitArray.readUnsignedExpGolombCodedInt();
int readUnsignedExpGolombCodedInt = parsableNalUnitBitArray.readUnsignedExpGolombCodedInt();
if (readUnsignedExpGolombCodedInt == 3) {
parsableNalUnitBitArray.skipBit();
}
int readUnsignedExpGolombCodedInt2 = parsableNalUnitBitArray.readUnsignedExpGolombCodedInt();
int readUnsignedExpGolombCodedInt3 = parsableNalUnitBitArray.readUnsignedExpGolombCodedInt();
if (parsableNalUnitBitArray.readBit()) {
int readUnsignedExpGolombCodedInt4 = parsableNalUnitBitArray.readUnsignedExpGolombCodedInt();
int readUnsignedExpGolombCodedInt5 = parsableNalUnitBitArray.readUnsignedExpGolombCodedInt();
int readUnsignedExpGolombCodedInt6 = parsableNalUnitBitArray.readUnsignedExpGolombCodedInt();
int readUnsignedExpGolombCodedInt7 = parsableNalUnitBitArray.readUnsignedExpGolombCodedInt();
readUnsignedExpGolombCodedInt2 -= ((readUnsignedExpGolombCodedInt == 1 || readUnsignedExpGolombCodedInt == 2) ? 2 : 1) * (readUnsignedExpGolombCodedInt4 + readUnsignedExpGolombCodedInt5);
readUnsignedExpGolombCodedInt3 -= (readUnsignedExpGolombCodedInt == 1 ? 2 : 1) * (readUnsignedExpGolombCodedInt6 + readUnsignedExpGolombCodedInt7);
}
parsableNalUnitBitArray.readUnsignedExpGolombCodedInt();
parsableNalUnitBitArray.readUnsignedExpGolombCodedInt();
int readUnsignedExpGolombCodedInt8 = parsableNalUnitBitArray.readUnsignedExpGolombCodedInt();
for (int i6 = parsableNalUnitBitArray.readBit() ? 0 : readBits; i6 <= readBits; i6++) {
parsableNalUnitBitArray.readUnsignedExpGolombCodedInt();
parsableNalUnitBitArray.readUnsignedExpGolombCodedInt();
parsableNalUnitBitArray.readUnsignedExpGolombCodedInt();
}
parsableNalUnitBitArray.readUnsignedExpGolombCodedInt();
parsableNalUnitBitArray.readUnsignedExpGolombCodedInt();
parsableNalUnitBitArray.readUnsignedExpGolombCodedInt();
parsableNalUnitBitArray.readUnsignedExpGolombCodedInt();
parsableNalUnitBitArray.readUnsignedExpGolombCodedInt();
parsableNalUnitBitArray.readUnsignedExpGolombCodedInt();
if (parsableNalUnitBitArray.readBit() && parsableNalUnitBitArray.readBit()) {
skipScalingList(parsableNalUnitBitArray);
}
parsableNalUnitBitArray.skipBits(2);
if (parsableNalUnitBitArray.readBit()) {
parsableNalUnitBitArray.skipBits(8);
parsableNalUnitBitArray.readUnsignedExpGolombCodedInt();
parsableNalUnitBitArray.readUnsignedExpGolombCodedInt();
parsableNalUnitBitArray.skipBit();
}
skipShortTermRefPicSets(parsableNalUnitBitArray);
if (parsableNalUnitBitArray.readBit()) {
for (int i7 = 0; i7 < parsableNalUnitBitArray.readUnsignedExpGolombCodedInt(); i7++) {
parsableNalUnitBitArray.skipBits(readUnsignedExpGolombCodedInt8 + 4 + 1);
}
}
parsableNalUnitBitArray.skipBits(2);
float f = 1.0f;
if (parsableNalUnitBitArray.readBit()) {
if (parsableNalUnitBitArray.readBit()) {
int readBits5 = parsableNalUnitBitArray.readBits(8);
if (readBits5 == 255) {
int readBits6 = parsableNalUnitBitArray.readBits(16);
int readBits7 = parsableNalUnitBitArray.readBits(16);
if (!(readBits6 == 0 || readBits7 == 0)) {
f = ((float) readBits6) / ((float) readBits7);
}
} else if (readBits5 < NalUnitUtil.ASPECT_RATIO_IDC_VALUES.length) {
f = NalUnitUtil.ASPECT_RATIO_IDC_VALUES[readBits5];
} else {
Log.w(TAG, "Unexpected aspect_ratio_idc value: " + readBits5);
}
}
if (parsableNalUnitBitArray.readBit()) {
parsableNalUnitBitArray.skipBit();
}
if (parsableNalUnitBitArray.readBit()) {
parsableNalUnitBitArray.skipBits(4);
if (parsableNalUnitBitArray.readBit()) {
parsableNalUnitBitArray.skipBits(24);
}
}
if (parsableNalUnitBitArray.readBit()) {
parsableNalUnitBitArray.readUnsignedExpGolombCodedInt();
parsableNalUnitBitArray.readUnsignedExpGolombCodedInt();
}
parsableNalUnitBitArray.skipBit();
if (parsableNalUnitBitArray.readBit()) {
readUnsignedExpGolombCodedInt3 *= 2;
}
}
return new Format.Builder().setId(str).setSampleMimeType(MimeTypes.VIDEO_H265).setCodecs(CodecSpecificDataUtil.buildHevcCodecString(readBits2, readBit, readBits3, i, iArr, readBits4)).setWidth(readUnsignedExpGolombCodedInt2).setHeight(readUnsignedExpGolombCodedInt3).setPixelWidthHeightRatio(f).setInitializationData(Collections.singletonList(bArr)).build();
}
private static void skipScalingList(ParsableNalUnitBitArray parsableNalUnitBitArray) {
for (int i = 0; i < 4; i++) {
int i2 = 0;
while (i2 < 6) {
int i3 = 1;
if (!parsableNalUnitBitArray.readBit()) {
parsableNalUnitBitArray.readUnsignedExpGolombCodedInt();
} else {
int min = Math.min(64, 1 << ((i << 1) + 4));
if (i > 1) {
parsableNalUnitBitArray.readSignedExpGolombCodedInt();
}
for (int i4 = 0; i4 < min; i4++) {
parsableNalUnitBitArray.readSignedExpGolombCodedInt();
}
}
if (i == 3) {
i3 = 3;
}
i2 += i3;
}
}
}
private static void skipShortTermRefPicSets(ParsableNalUnitBitArray parsableNalUnitBitArray) {
int readUnsignedExpGolombCodedInt = parsableNalUnitBitArray.readUnsignedExpGolombCodedInt();
boolean z = false;
int i = 0;
for (int i2 = 0; i2 < readUnsignedExpGolombCodedInt; i2++) {
if (i2 != 0) {
z = parsableNalUnitBitArray.readBit();
}
if (z) {
parsableNalUnitBitArray.skipBit();
parsableNalUnitBitArray.readUnsignedExpGolombCodedInt();
for (int i3 = 0; i3 <= i; i3++) {
if (parsableNalUnitBitArray.readBit()) {
parsableNalUnitBitArray.skipBit();
}
}
} else {
int readUnsignedExpGolombCodedInt2 = parsableNalUnitBitArray.readUnsignedExpGolombCodedInt();
int readUnsignedExpGolombCodedInt3 = parsableNalUnitBitArray.readUnsignedExpGolombCodedInt();
int i4 = readUnsignedExpGolombCodedInt2 + readUnsignedExpGolombCodedInt3;
for (int i5 = 0; i5 < readUnsignedExpGolombCodedInt2; i5++) {
parsableNalUnitBitArray.readUnsignedExpGolombCodedInt();
parsableNalUnitBitArray.skipBit();
}
for (int i6 = 0; i6 < readUnsignedExpGolombCodedInt3; i6++) {
parsableNalUnitBitArray.readUnsignedExpGolombCodedInt();
parsableNalUnitBitArray.skipBit();
}
i = i4;
}
}
}
@EnsuresNonNull({"output", "sampleReader"})
private void assertTracksCreated() {
Assertions.checkStateNotNull(this.output);
Util.castNonNull(this.sampleReader);
}
private static final class SampleReader {
private static final int FIRST_SLICE_FLAG_OFFSET = 2;
private boolean isFirstPrefixNalUnit;
private boolean isFirstSlice;
private boolean lookingForFirstSliceFlag;
private int nalUnitBytesRead;
private boolean nalUnitHasKeyframeData;
private long nalUnitPosition;
private long nalUnitTimeUs;
private final TrackOutput output;
private boolean readingPrefix;
private boolean readingSample;
private boolean sampleIsKeyframe;
private long samplePosition;
private long sampleTimeUs;
private static boolean isPrefixNalUnit(int i) {
return (32 <= i && i <= 35) || i == 39;
}
private static boolean isVclBodyNalUnit(int i) {
return i < 32 || i == 40;
}
public SampleReader(TrackOutput trackOutput) {
this.output = trackOutput;
}
public void reset() {
this.lookingForFirstSliceFlag = false;
this.isFirstSlice = false;
this.isFirstPrefixNalUnit = false;
this.readingSample = false;
this.readingPrefix = false;
}
public void startNalUnit(long j, int i, int i2, long j2, boolean z) {
boolean z2 = false;
this.isFirstSlice = false;
this.isFirstPrefixNalUnit = false;
this.nalUnitTimeUs = j2;
this.nalUnitBytesRead = 0;
this.nalUnitPosition = j;
if (!isVclBodyNalUnit(i2)) {
if (this.readingSample && !this.readingPrefix) {
if (z) {
outputSample(i);
}
this.readingSample = false;
}
if (isPrefixNalUnit(i2)) {
this.isFirstPrefixNalUnit = !this.readingPrefix;
this.readingPrefix = true;
}
}
boolean z3 = i2 >= 16 && i2 <= 21;
this.nalUnitHasKeyframeData = z3;
if (z3 || i2 <= 9) {
z2 = true;
}
this.lookingForFirstSliceFlag = z2;
}
public void readNalUnitData(byte[] bArr, int i, int i2) {
if (this.lookingForFirstSliceFlag) {
int i3 = this.nalUnitBytesRead;
int i4 = (i + 2) - i3;
if (i4 < i2) {
this.isFirstSlice = (bArr[i4] & 128) != 0;
this.lookingForFirstSliceFlag = false;
return;
}
this.nalUnitBytesRead = i3 + (i2 - i);
}
}
public void endNalUnit(long j, int i, boolean z) {
if (this.readingPrefix && this.isFirstSlice) {
this.sampleIsKeyframe = this.nalUnitHasKeyframeData;
this.readingPrefix = false;
} else if (this.isFirstPrefixNalUnit || this.isFirstSlice) {
if (z && this.readingSample) {
outputSample(i + ((int) (j - this.nalUnitPosition)));
}
this.samplePosition = this.nalUnitPosition;
this.sampleTimeUs = this.nalUnitTimeUs;
this.sampleIsKeyframe = this.nalUnitHasKeyframeData;
this.readingSample = true;
}
}
private void outputSample(int i) {
long j = this.sampleTimeUs;
if (j != C.TIME_UNSET) {
boolean z = this.sampleIsKeyframe;
this.output.sampleMetadata(j, z ? 1 : 0, (int) (this.nalUnitPosition - this.samplePosition), i, (TrackOutput.CryptoData) null);
}
}
}
}
Download file