Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d8e8a9a4 authored by Santiago Seifert's avatar Santiago Seifert Committed by Automerger Merge Worker
Browse files

Merge "Align CryptoInfo value and identity equality" into rvc-dev am: 9a2fdad0 am: 1a9fb93f

Change-Id: I8068bb83fc87ed4e1a60f69627a595d6f24e185a
parents 3237ce33 1a9fb93f
Loading
Loading
Loading
Loading
+90 −34
Original line number Original line Diff line number Diff line
@@ -402,9 +402,9 @@ public final class MediaParser {
         *     onSampleDataFound(int, MediaParser.InputReader)} for the specified track, since the
         *     onSampleDataFound(int, MediaParser.InputReader)} for the specified track, since the
         *     last byte belonging to the sample whose metadata is being passed.
         *     last byte belonging to the sample whose metadata is being passed.
         * @param cryptoInfo Encryption data required to decrypt the sample. May be null for
         * @param cryptoInfo Encryption data required to decrypt the sample. May be null for
         *     unencrypted samples. MediaParser may reuse {@link CryptoInfo} instances to avoid
         *     unencrypted samples. Implementors should treat any output {@link CryptoInfo}
         *     allocations, so implementations of this method must not write to or keep reference to
         *     instances as immutable. MediaParser will not modify any output {@code cryptoInfos}
         *     the fields of this parameter.
         *     and implementors should not modify them either.
         */
         */
        void onSampleCompleted(
        void onSampleCompleted(
                int trackIndex,
                int trackIndex,
@@ -1409,23 +1409,28 @@ public final class MediaParser {
    private class TrackOutputAdapter implements TrackOutput {
    private class TrackOutputAdapter implements TrackOutput {


        private final int mTrackIndex;
        private final int mTrackIndex;
        private final CryptoInfo mCryptoInfo;

        private CryptoInfo mLastOutputCryptoInfo;
        private CryptoInfo.Pattern mLastOutputEncryptionPattern;
        private CryptoData mLastReceivedCryptoData;


        @EncryptionDataReadState private int mEncryptionDataReadState;
        @EncryptionDataReadState private int mEncryptionDataReadState;
        private int mEncryptionDataSizeToSubtractFromSampleDataSize;
        private int mEncryptionDataSizeToSubtractFromSampleDataSize;
        private int mEncryptionVectorSize;
        private int mEncryptionVectorSize;
        private byte[] mScratchIvSpace;
        private int mSubsampleEncryptionDataSize;
        private int[] mScratchSubsampleEncryptedBytesCount;
        private int[] mScratchSubsampleClearBytesCount;
        private boolean mHasSubsampleEncryptionData;
        private boolean mHasSubsampleEncryptionData;
        private CryptoInfo.Pattern mEncryptionPattern;
        private int mSkippedSupplementalDataBytes;
        private int mSkippedSupplementalDataBytes;


        private TrackOutputAdapter(int trackIndex) {
        private TrackOutputAdapter(int trackIndex) {
            mTrackIndex = trackIndex;
            mTrackIndex = trackIndex;
            mCryptoInfo = new CryptoInfo();
            mScratchIvSpace = new byte[16]; // Size documented in CryptoInfo.
            mCryptoInfo.iv = new byte[16]; // Size documented in CryptoInfo.
            mScratchSubsampleEncryptedBytesCount = new int[32];
            mCryptoInfo.numBytesOfClearData = new int[0];
            mScratchSubsampleClearBytesCount = new int[32];
            mCryptoInfo.numBytesOfEncryptedData = new int[0];
            mEncryptionDataReadState = STATE_READING_SIGNAL_BYTE;
            mEncryptionDataReadState = STATE_READING_SIGNAL_BYTE;
            mEncryptionPattern =
            mLastOutputEncryptionPattern =
                    new CryptoInfo.Pattern(/* blocksToEncrypt= */ 0, /* blocksToSkip= */ 0);
                    new CryptoInfo.Pattern(/* blocksToEncrypt= */ 0, /* blocksToSkip= */ 0);
        }
        }


@@ -1466,35 +1471,39 @@ public final class MediaParser {
                            mEncryptionDataReadState = STATE_READING_INIT_VECTOR;
                            mEncryptionDataReadState = STATE_READING_INIT_VECTOR;
                            break;
                            break;
                        case STATE_READING_INIT_VECTOR:
                        case STATE_READING_INIT_VECTOR:
                            Arrays.fill(mCryptoInfo.iv, (byte) 0); // Ensure 0-padding.
                            Arrays.fill(mScratchIvSpace, (byte) 0); // Ensure 0-padding.
                            data.readBytes(mCryptoInfo.iv, /* offset= */ 0, mEncryptionVectorSize);
                            data.readBytes(mScratchIvSpace, /* offset= */ 0, mEncryptionVectorSize);
                            length -= mEncryptionVectorSize;
                            length -= mEncryptionVectorSize;
                            if (mHasSubsampleEncryptionData) {
                            if (mHasSubsampleEncryptionData) {
                                mEncryptionDataReadState = STATE_READING_SUBSAMPLE_ENCRYPTION_SIZE;
                                mEncryptionDataReadState = STATE_READING_SUBSAMPLE_ENCRYPTION_SIZE;
                            } else {
                            } else {
                                mCryptoInfo.numSubSamples = 0;
                                mSubsampleEncryptionDataSize = 0;
                                mEncryptionDataReadState = STATE_READING_SIGNAL_BYTE;
                                mEncryptionDataReadState = STATE_READING_SIGNAL_BYTE;
                            }
                            }
                            break;
                            break;
                        case STATE_READING_SUBSAMPLE_ENCRYPTION_SIZE:
                        case STATE_READING_SUBSAMPLE_ENCRYPTION_SIZE:
                            int numSubSamples = data.readUnsignedShort();
                            mSubsampleEncryptionDataSize = data.readUnsignedShort();
                            mCryptoInfo.numSubSamples = numSubSamples;
                            if (mScratchSubsampleClearBytesCount.length
                            if (mCryptoInfo.numBytesOfClearData.length < numSubSamples) {
                                    < mSubsampleEncryptionDataSize) {
                                mCryptoInfo.numBytesOfClearData = new int[numSubSamples];
                                mScratchSubsampleClearBytesCount =
                                mCryptoInfo.numBytesOfEncryptedData = new int[numSubSamples];
                                        new int[mSubsampleEncryptionDataSize];
                                mScratchSubsampleEncryptedBytesCount =
                                        new int[mSubsampleEncryptionDataSize];
                            }
                            }
                            length -= 2;
                            length -= 2;
                            mEncryptionDataSizeToSubtractFromSampleDataSize +=
                            mEncryptionDataSizeToSubtractFromSampleDataSize +=
                                    2 + numSubSamples * BYTES_PER_SUBSAMPLE_ENCRYPTION_ENTRY;
                                    2
                                            + mSubsampleEncryptionDataSize
                                                    * BYTES_PER_SUBSAMPLE_ENCRYPTION_ENTRY;
                            mEncryptionDataReadState = STATE_READING_SUBSAMPLE_ENCRYPTION_DATA;
                            mEncryptionDataReadState = STATE_READING_SUBSAMPLE_ENCRYPTION_DATA;
                            break;
                            break;
                        case STATE_READING_SUBSAMPLE_ENCRYPTION_DATA:
                        case STATE_READING_SUBSAMPLE_ENCRYPTION_DATA:
                            for (int i = 0; i < mCryptoInfo.numSubSamples; i++) {
                            for (int i = 0; i < mSubsampleEncryptionDataSize; i++) {
                                mCryptoInfo.numBytesOfClearData[i] = data.readUnsignedShort();
                                mScratchSubsampleClearBytesCount[i] = data.readUnsignedShort();
                                mCryptoInfo.numBytesOfEncryptedData[i] = data.readInt();
                                mScratchSubsampleEncryptedBytesCount[i] = data.readInt();
                            }
                            }
                            length -=
                            length -=
                                    mCryptoInfo.numSubSamples
                                    mSubsampleEncryptionDataSize
                                            * BYTES_PER_SUBSAMPLE_ENCRYPTION_ENTRY;
                                            * BYTES_PER_SUBSAMPLE_ENCRYPTION_ENTRY;
                            mEncryptionDataReadState = STATE_READING_SIGNAL_BYTE;
                            mEncryptionDataReadState = STATE_READING_SIGNAL_BYTE;
                            if (length != 0) {
                            if (length != 0) {
@@ -1536,24 +1545,71 @@ public final class MediaParser {
            if (cryptoData == null) {
            if (cryptoData == null) {
                // The sample is not encrypted.
                // The sample is not encrypted.
                return null;
                return null;
            }
            } else if (mInBandCryptoInfo) {
            mCryptoInfo.key = cryptoData.encryptionKey;
                if (cryptoData != mLastReceivedCryptoData) {
            // ExoPlayer modes match MediaCodec modes.
                    mLastOutputCryptoInfo =
            mCryptoInfo.mode = cryptoData.cryptoMode;
                            createNewCryptoInfoAndPopulateWithCryptoData(cryptoData);
            if (cryptoData.clearBlocks != 0) {
                }
                // Content is pattern-encrypted.
            } else /* We must populate the full CryptoInfo. */ {
                mCryptoInfo.setPattern(mEncryptionPattern);
                // CryptoInfo.pattern is not accessible to the user, so the user needs to feed
                mEncryptionPattern.set(cryptoData.encryptedBlocks, cryptoData.clearBlocks);
                // this CryptoInfo directly to MediaCodec. We need to create a new CryptoInfo per
                // sample because of per-sample initialization vector changes.
                CryptoInfo newCryptoInfo = createNewCryptoInfoAndPopulateWithCryptoData(cryptoData);
                newCryptoInfo.iv = Arrays.copyOf(mScratchIvSpace, mScratchIvSpace.length);
                boolean canReuseSubsampleInfo =
                        mLastOutputCryptoInfo != null
                                && mLastOutputCryptoInfo.numSubSamples
                                        == mSubsampleEncryptionDataSize;
                for (int i = 0; i < mSubsampleEncryptionDataSize && canReuseSubsampleInfo; i++) {
                    canReuseSubsampleInfo =
                            mLastOutputCryptoInfo.numBytesOfClearData[i]
                                            == mScratchSubsampleClearBytesCount[i]
                                    && mLastOutputCryptoInfo.numBytesOfEncryptedData[i]
                                            == mScratchSubsampleEncryptedBytesCount[i];
                }
                newCryptoInfo.numSubSamples = mSubsampleEncryptionDataSize;
                if (canReuseSubsampleInfo) {
                    newCryptoInfo.numBytesOfClearData = mLastOutputCryptoInfo.numBytesOfClearData;
                    newCryptoInfo.numBytesOfEncryptedData =
                            mLastOutputCryptoInfo.numBytesOfEncryptedData;
                } else {
                } else {
                mCryptoInfo.setPattern(null);
                    newCryptoInfo.numBytesOfClearData =
                            Arrays.copyOf(
                                    mScratchSubsampleClearBytesCount, mSubsampleEncryptionDataSize);
                    newCryptoInfo.numBytesOfEncryptedData =
                            Arrays.copyOf(
                                    mScratchSubsampleEncryptedBytesCount,
                                    mSubsampleEncryptionDataSize);
                }
                mLastOutputCryptoInfo = newCryptoInfo;
            }
            }
            return mCryptoInfo;
            mLastReceivedCryptoData = cryptoData;
            return mLastOutputCryptoInfo;
        }

        private CryptoInfo createNewCryptoInfoAndPopulateWithCryptoData(CryptoData cryptoData) {
            CryptoInfo cryptoInfo = new CryptoInfo();
            cryptoInfo.key = cryptoData.encryptionKey;
            cryptoInfo.mode = cryptoData.cryptoMode;
            if (cryptoData.clearBlocks != mLastOutputEncryptionPattern.getSkipBlocks()
                    || cryptoData.encryptedBlocks
                            != mLastOutputEncryptionPattern.getEncryptBlocks()) {
                mLastOutputEncryptionPattern =
                        new CryptoInfo.Pattern(cryptoData.encryptedBlocks, cryptoData.clearBlocks);
            }
            cryptoInfo.setPattern(mLastOutputEncryptionPattern);
            return cryptoInfo;
        }
        }


        private void outputSampleData(ParsableByteArray data, int length) {
        private void outputSampleData(ParsableByteArray data, int length) {
            mScratchParsableByteArrayAdapter.resetWithByteArray(data, length);
            mScratchParsableByteArrayAdapter.resetWithByteArray(data, length);
            try {
            try {
                mOutputConsumer.onSampleDataFound(mTrackIndex, mScratchParsableByteArrayAdapter);
                // Read all bytes from data. ExoPlayer extractors expect all sample data to be
                // consumed by TrackOutput implementations when passing a ParsableByteArray.
                while (mScratchParsableByteArrayAdapter.getLength() > 0) {
                    mOutputConsumer.onSampleDataFound(
                            mTrackIndex, mScratchParsableByteArrayAdapter);
                }
            } catch (IOException e) {
            } catch (IOException e) {
                // Unexpected.
                // Unexpected.
                throw new RuntimeException(e);
                throw new RuntimeException(e);