/** Parses a sidx atom (defined in 14496-12). */ private static ChunkIndex parseSidx(ParsableByteArray atom, long inputPosition) throws ParserException { atom.setPosition(Atom.HEADER_SIZE); int fullAtom = atom.readInt(); int version = Atom.parseFullAtomVersion(fullAtom); atom.skipBytes(4); long timescale = atom.readUnsignedInt(); long earliestPresentationTime; long offset = inputPosition; if (version == 0) { earliestPresentationTime = atom.readUnsignedInt(); offset += atom.readUnsignedInt(); } else { earliestPresentationTime = atom.readUnsignedLongToLong(); offset += atom.readUnsignedLongToLong(); } atom.skipBytes(2); int referenceCount = atom.readUnsignedShort(); int[] sizes = new int[referenceCount]; long[] offsets = new long[referenceCount]; long[] durationsUs = new long[referenceCount]; long[] timesUs = new long[referenceCount]; long time = earliestPresentationTime; long timeUs = Util.scaleLargeTimestamp(time, C.MICROS_PER_SECOND, timescale); for (int i = 0; i < referenceCount; i++) { int firstInt = atom.readInt(); int type = 0x80000000 & firstInt; if (type != 0) { throw new ParserException("Unhandled indirect reference"); } long referenceDuration = atom.readUnsignedInt(); sizes[i] = 0x7fffffff & firstInt; offsets[i] = offset; // Calculate time and duration values such that any rounding errors are consistent. i.e. That // timesUs[i] + durationsUs[i] == timesUs[i + 1]. timesUs[i] = timeUs; time += referenceDuration; timeUs = Util.scaleLargeTimestamp(time, C.MICROS_PER_SECOND, timescale); durationsUs[i] = timeUs - timesUs[i]; atom.skipBytes(4); offset += sizes[i]; } return new ChunkIndex(sizes, offsets, durationsUs, timesUs); }
private int appendSampleEncryptionData(ParsableByteArray sampleEncryptionData) { int sampleDescriptionIndex = fragmentRun.header.sampleDescriptionIndex; TrackEncryptionBox encryptionBox = track.sampleDescriptionEncryptionBoxes[sampleDescriptionIndex]; int vectorSize = encryptionBox.initializationVectorSize; boolean subsampleEncryption = fragmentRun.sampleHasSubsampleEncryptionTable[sampleIndex]; // Write the signal byte, containing the vector size and the subsample encryption flag. encryptionSignalByte.data[0] = (byte) (vectorSize | (subsampleEncryption ? 0x80 : 0)); encryptionSignalByte.setPosition(0); trackOutput.sampleData(encryptionSignalByte, 1); // Write the vector. trackOutput.sampleData(sampleEncryptionData, vectorSize); // If we don't have subsample encryption data, we're done. if (!subsampleEncryption) { return 1 + vectorSize; } // Write the subsample encryption data. int subsampleCount = sampleEncryptionData.readUnsignedShort(); sampleEncryptionData.skipBytes(-2); int subsampleDataLength = 2 + 6 * subsampleCount; trackOutput.sampleData(sampleEncryptionData, subsampleDataLength); return 1 + vectorSize + subsampleDataLength; }