diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4Extractor.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4Extractor.java index 95e51c9cd7..a67c990193 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4Extractor.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4Extractor.java @@ -731,7 +731,7 @@ public final class FragmentedMp4Extractor implements Extractor { private static void parseSaiz(TrackEncryptionBox encryptionBox, ParsableByteArray saiz, TrackFragment out) throws ParserException { - int vectorSize = encryptionBox.initializationVectorSize; + int vectorSize = encryptionBox.perSampleIvSize; saiz.setPosition(Atom.HEADER_SIZE); int fullAtom = saiz.readInt(); int flags = Atom.parseFullAtomFlags(fullAtom); @@ -1266,11 +1266,9 @@ public final class FragmentedMp4Extractor implements Extractor { // Encryption data. TrackOutput.CryptoData cryptoData = null; - if (fragment.definesEncryptionData) { + TrackEncryptionBox encryptionBox = currentTrackBundle.getEncryptionBoxIfEncrypted(); + if (encryptionBox != null) { sampleFlags |= C.BUFFER_FLAG_ENCRYPTED; - TrackEncryptionBox encryptionBox = fragment.trackEncryptionBox != null - ? fragment.trackEncryptionBox - : track.getSampleDescriptionEncryptionBox(fragment.header.sampleDescriptionIndex); cryptoData = encryptionBox.cryptoData; } @@ -1467,16 +1465,16 @@ public final class FragmentedMp4Extractor implements Extractor { * @return The number of written bytes. */ public int outputSampleEncryptionData() { - if (!fragment.definesEncryptionData) { + TrackEncryptionBox encryptionBox = getEncryptionBoxIfEncrypted(); + if (encryptionBox == null) { return 0; } - TrackEncryptionBox encryptionBox = getEncryptionBox(); ParsableByteArray initializationVectorData; int vectorSize; - if (encryptionBox.initializationVectorSize != 0) { + if (encryptionBox.perSampleIvSize != 0) { initializationVectorData = fragment.sampleEncryptionData; - vectorSize = encryptionBox.initializationVectorSize; + vectorSize = encryptionBox.perSampleIvSize; } else { // The default initialization vector should be used. byte[] initVectorData = encryptionBox.defaultInitializationVector; @@ -1485,7 +1483,7 @@ public final class FragmentedMp4Extractor implements Extractor { vectorSize = initVectorData.length; } - boolean subsampleEncryption = fragment.sampleHasSubsampleEncryptionTable[currentSampleIndex]; + boolean subsampleEncryption = fragment.sampleHasSubsampleEncryptionTable(currentSampleIndex); // Write the signal byte, containing the vector size and the subsample encryption flag. encryptionSignalByte.data[0] = (byte) (vectorSize | (subsampleEncryption ? 0x80 : 0)); @@ -1508,25 +1506,27 @@ public final class FragmentedMp4Extractor implements Extractor { /** Skips the encryption data for the current sample. */ private void skipSampleEncryptionData() { - if (!fragment.definesEncryptionData) { + TrackEncryptionBox encryptionBox = getEncryptionBoxIfEncrypted(); + if (encryptionBox == null) { return; } ParsableByteArray sampleEncryptionData = fragment.sampleEncryptionData; - TrackEncryptionBox encryptionBox = getEncryptionBox(); - if (encryptionBox.initializationVectorSize != 0) { - sampleEncryptionData.skipBytes(encryptionBox.initializationVectorSize); + if (encryptionBox.perSampleIvSize != 0) { + sampleEncryptionData.skipBytes(encryptionBox.perSampleIvSize); } - if (fragment.sampleHasSubsampleEncryptionTable[currentSampleIndex]) { + if (fragment.sampleHasSubsampleEncryptionTable(currentSampleIndex)) { sampleEncryptionData.skipBytes(6 * sampleEncryptionData.readUnsignedShort()); } } - private TrackEncryptionBox getEncryptionBox() { + private TrackEncryptionBox getEncryptionBoxIfEncrypted() { int sampleDescriptionIndex = fragment.header.sampleDescriptionIndex; - return fragment.trackEncryptionBox != null - ? fragment.trackEncryptionBox - : track.getSampleDescriptionEncryptionBox(sampleDescriptionIndex); + TrackEncryptionBox encryptionBox = + fragment.trackEncryptionBox != null + ? fragment.trackEncryptionBox + : track.getSampleDescriptionEncryptionBox(sampleDescriptionIndex); + return encryptionBox != null && encryptionBox.isEncrypted ? encryptionBox : null; } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/TrackEncryptionBox.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/TrackEncryptionBox.java index d39aae0c5f..54207f351f 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/TrackEncryptionBox.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/TrackEncryptionBox.java @@ -45,33 +45,36 @@ public final class TrackEncryptionBox { */ public final TrackOutput.CryptoData cryptoData; - /** - * The initialization vector size in bytes for the samples in the corresponding sample group. - */ - public final int initializationVectorSize; + /** The initialization vector size in bytes for the samples in the corresponding sample group. */ + public final int perSampleIvSize; /** - * If {@link #initializationVectorSize} is 0, holds the default initialization vector as defined - * in the track encryption box or sample group description box. Null otherwise. + * If {@link #perSampleIvSize} is 0, holds the default initialization vector as defined in the + * track encryption box or sample group description box. Null otherwise. */ public final byte[] defaultInitializationVector; /** * @param isEncrypted See {@link #isEncrypted}. * @param schemeType See {@link #schemeType}. - * @param initializationVectorSize See {@link #initializationVectorSize}. + * @param perSampleIvSize See {@link #perSampleIvSize}. * @param keyId See {@link TrackOutput.CryptoData#encryptionKey}. * @param defaultEncryptedBlocks See {@link TrackOutput.CryptoData#encryptedBlocks}. * @param defaultClearBlocks See {@link TrackOutput.CryptoData#clearBlocks}. * @param defaultInitializationVector See {@link #defaultInitializationVector}. */ - public TrackEncryptionBox(boolean isEncrypted, @Nullable String schemeType, - int initializationVectorSize, byte[] keyId, int defaultEncryptedBlocks, - int defaultClearBlocks, @Nullable byte[] defaultInitializationVector) { - Assertions.checkArgument(initializationVectorSize == 0 ^ defaultInitializationVector == null); + public TrackEncryptionBox( + boolean isEncrypted, + @Nullable String schemeType, + int perSampleIvSize, + byte[] keyId, + int defaultEncryptedBlocks, + int defaultClearBlocks, + @Nullable byte[] defaultInitializationVector) { + Assertions.checkArgument(perSampleIvSize == 0 ^ defaultInitializationVector == null); this.isEncrypted = isEncrypted; this.schemeType = schemeType; - this.initializationVectorSize = initializationVectorSize; + this.perSampleIvSize = perSampleIvSize; this.defaultInitializationVector = defaultInitializationVector; cryptoData = new TrackOutput.CryptoData(schemeToCryptoMode(schemeType), keyId, defaultEncryptedBlocks, defaultClearBlocks); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/TrackFragment.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/TrackFragment.java index 5ac673d037..51ec2bf282 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/TrackFragment.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/TrackFragment.java @@ -190,4 +190,8 @@ import java.io.IOException; return sampleDecodingTimeTable[index] + sampleCompositionTimeOffsetTable[index]; } + /** Returns whether the sample at the given index has a subsample encryption table. */ + public boolean sampleHasSubsampleEncryptionTable(int index) { + return definesEncryptionData && sampleHasSubsampleEncryptionTable[index]; + } }