private void readEncryptionData(ExtractorInput input) throws IOException, InterruptedException { int bytesToSkip = (int) (fragmentRun.auxiliaryDataPosition - input.getPosition()); checkState(bytesToSkip >= 0, "Offset to encryption data was negative."); input.skipFully(bytesToSkip); fragmentRun.fillEncryptionData(input); parserState = STATE_READING_SAMPLE_START; }
private void readAtomPayload(ExtractorInput input) throws IOException, InterruptedException { int atomPayloadSize = (int) atomSize - atomHeaderBytesRead; if (atomData != null) { input.readFully(atomData.data, Atom.HEADER_SIZE, atomPayloadSize); onLeafAtomRead(new LeafAtom(atomType, atomData), input.getPosition()); } else { input.skipFully(atomPayloadSize); } long currentPosition = input.getPosition(); while (!containerAtoms.isEmpty() && containerAtoms.peek().endPosition == currentPosition) { onContainerAtomRead(containerAtoms.pop()); } enterReadingAtomHeaderState(); }
/** * Attempts to extract the next sample in the current mdat atom. * * <p>If there are no more samples in the current mdat atom then the parser state is transitioned * to {@link #STATE_READING_ATOM_HEADER} and {@code false} is returned. * * <p>It is possible for a sample to be extracted in part in the case that an exception is thrown. * In this case the method can be called again to extract the remainder of the sample. * * @param input The {@link ExtractorInput} from which to read data. * @return True if a sample was extracted. False otherwise. * @throws IOException If an error occurs reading from the input. * @throws InterruptedException If the thread is interrupted. */ private boolean readSample(ExtractorInput input) throws IOException, InterruptedException { if (sampleIndex == 0) { int bytesToSkip = (int) (fragmentRun.dataPosition - input.getPosition()); checkState(bytesToSkip >= 0, "Offset to sample data was negative."); input.skipFully(bytesToSkip); } if (sampleIndex >= fragmentRun.length) { int bytesToSkip = (int) (endOfMdatPosition - input.getPosition()); checkState(bytesToSkip >= 0, "Offset to end of mdat was negative."); input.skipFully(bytesToSkip); // We've run out of samples in the current mdat atom. enterReadingAtomHeaderState(); return false; } if (parserState == STATE_READING_SAMPLE_START) { sampleSize = fragmentRun.sampleSizeTable[sampleIndex]; if (fragmentRun.definesEncryptionData) { sampleBytesWritten = appendSampleEncryptionData(fragmentRun.sampleEncryptionData); sampleSize += sampleBytesWritten; } else { sampleBytesWritten = 0; } sampleCurrentNalBytesRemaining = 0; parserState = STATE_READING_SAMPLE_CONTINUE; } if (track.nalUnitLengthFieldLength != -1) { // Zero the top three bytes of the array that we'll use to parse nal unit lengths, in case // they're only 1 or 2 bytes long. byte[] nalLengthData = nalLength.data; nalLengthData[0] = 0; nalLengthData[1] = 0; nalLengthData[2] = 0; int nalUnitLengthFieldLength = track.nalUnitLengthFieldLength; int nalUnitLengthFieldLengthDiff = 4 - track.nalUnitLengthFieldLength; // NAL units are length delimited, but the decoder requires start code delimited units. // Loop until we've written the sample to the track output, replacing length delimiters with // start codes as we encounter them. while (sampleBytesWritten < sampleSize) { if (sampleCurrentNalBytesRemaining == 0) { // Read the NAL length so that we know where we find the next one. input.readFully(nalLength.data, nalUnitLengthFieldLengthDiff, nalUnitLengthFieldLength); nalLength.setPosition(0); sampleCurrentNalBytesRemaining = nalLength.readUnsignedIntToInt(); // Write a start code for the current NAL unit. nalStartCode.setPosition(0); trackOutput.sampleData(nalStartCode, 4); sampleBytesWritten += 4; sampleSize += nalUnitLengthFieldLengthDiff; } else { // Write the payload of the NAL unit. int writtenBytes = trackOutput.sampleData(input, sampleCurrentNalBytesRemaining, false); sampleBytesWritten += writtenBytes; sampleCurrentNalBytesRemaining -= writtenBytes; } } } else { while (sampleBytesWritten < sampleSize) { int writtenBytes = trackOutput.sampleData(input, sampleSize - sampleBytesWritten, false); sampleBytesWritten += writtenBytes; } } long sampleTimeUs = fragmentRun.getSamplePresentationTime(sampleIndex) * 1000L; int sampleFlags = (fragmentRun.definesEncryptionData ? C.SAMPLE_FLAG_ENCRYPTED : 0) | (fragmentRun.sampleIsSyncFrameTable[sampleIndex] ? C.SAMPLE_FLAG_SYNC : 0); int sampleDescriptionIndex = fragmentRun.header.sampleDescriptionIndex; byte[] encryptionKey = fragmentRun.definesEncryptionData ? track.sampleDescriptionEncryptionBoxes[sampleDescriptionIndex].keyId : null; trackOutput.sampleMetadata(sampleTimeUs, sampleFlags, sampleSize, 0, encryptionKey); sampleIndex++; parserState = STATE_READING_SAMPLE_START; return true; }