class CencDecryptingSampleList extends AbstractList<Sample> {

    private RangeStartMap<Integer, SampleEntry> sampleEntries;
    private List<CencSampleAuxiliaryDataFormat> sencInfo;
    private RangeStartMap<Integer, SecretKey> keys = new RangeStartMap<>();
    private List<Sample> parent;

    public CencDecryptingSampleList(
            RangeStartMap<Integer, SecretKey> keys,
            RangeStartMap<Integer, SampleEntry> sampleEntries,
            List<Sample> parent,
            List<CencSampleAuxiliaryDataFormat> sencInfo
    ) {
        this.sampleEntries = sampleEntries;
        this.sencInfo = sencInfo;
        this.keys = keys;
        this.parent = parent;
    }

    private String getSchemeType(SampleEntry s) {
        SchemeTypeBox schm = Path.getPath((Container) s, "sinf/schm");

         assert schm != null : "Cannot get cipher without schemetypebox";
        return schm.getSchemeType();
    }

    private Cipher getCipher(SecretKey sk, byte[] iv, SampleEntry se) {

        byte[] fullIv = new byte[16];
        System.arraycopy(iv, 0, fullIv, 0, iv.length);
        // The IV
        try {
            String schemeType = getSchemeType(se);
            if ("cenc".equals(schemeType) || "piff".equals(schemeType)) {
                Cipher c = Cipher.getInstance("AES/CTR/NoPadding");
                c.init(Cipher.DECRYPT_MODE, sk, new IvParameterSpec(fullIv));
                return c;
            } else if ("cbc1".equals(schemeType)) {
                Cipher c = Cipher.getInstance("AES/CBC/NoPadding");
                c.init(Cipher.DECRYPT_MODE, sk, new IvParameterSpec(fullIv));
                return c;
            } else {
                throw new RuntimeException("Only cenc & cbc1 is supported as encryptionAlgo");
            }
        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException e) {
            throw new RuntimeException(e);
        }


    }

    @Override
    public Sample get(int index) {<FILL_FUNCTION_BODY>}

    @Override
    public int size() {
        return parent.size();
    }
}

        if (keys.get(index) != null) {
            Sample encSample = parent.get(index);
            final ByteBuffer encSampleBuffer = encSample.asByteBuffer();
            ((Buffer)encSampleBuffer).rewind();
            final ByteBuffer decSampleBuffer = ByteBuffer.allocate(encSampleBuffer.limit());
            final CencSampleAuxiliaryDataFormat sencEntry = sencInfo.get(index);
            Cipher cipher = getCipher(keys.get(index), sencEntry.iv, encSample.getSampleEntry());

            try {
                if (sencEntry.pairs != null && sencEntry.pairs.length > 0) {

                    for (CencSampleAuxiliaryDataFormat.Pair pair : sencEntry.pairs) {
                        final int clearBytes = pair.clear();
                        final int encrypted = l2i(pair.encrypted());

                        byte[] clears = new byte[clearBytes];
                        encSampleBuffer.get(clears);
                        decSampleBuffer.put(clears);
                        if (encrypted > 0) {
                            byte[] encs = new byte[encrypted];
                            encSampleBuffer.get(encs);
                            final byte[] decr = cipher.update(encs);
                            decSampleBuffer.put(decr);
                        }

                    }
                    if (encSampleBuffer.remaining() > 0) {
                        System.err.println("Decrypted sample " + index + " but still data remaining: " + encSample.getSize());
                    }
                    decSampleBuffer.put(cipher.doFinal());
                } else {
                    byte[] fullyEncryptedSample = new byte[encSampleBuffer.limit()];
                    encSampleBuffer.get(fullyEncryptedSample);
                    String schemeType = getSchemeType(encSample.getSampleEntry());
                    if ("cbc1".equals(schemeType)) {
                        int encryptedLength = fullyEncryptedSample.length / 16 * 16;
                        decSampleBuffer.put(cipher.doFinal(fullyEncryptedSample, 0, encryptedLength));
                        decSampleBuffer.put(fullyEncryptedSample, encryptedLength, fullyEncryptedSample.length - encryptedLength);
                    } else if ("cenc".equals(schemeType)) {
                        decSampleBuffer.put(cipher.doFinal(fullyEncryptedSample));
                    } else if ("piff".equals(schemeType)) {
                        decSampleBuffer.put(cipher.doFinal(fullyEncryptedSample));
                    } else {
                        throw new RuntimeException("unknown encryption algo");
                    }
                }
                ((Buffer)encSampleBuffer).rewind();
            } catch (IllegalBlockSizeException | BadPaddingException e) {
                throw new RuntimeException(e);
            }
            ((Buffer)decSampleBuffer).rewind();
            return new SampleImpl(decSampleBuffer, sampleEntries.get(index));
        } else {
            return parent.get(index);
        }
    
<methods>public boolean add(org.mp4parser.muxer.Sample) ,public void add(int, org.mp4parser.muxer.Sample) ,public boolean addAll(int, Collection<? extends org.mp4parser.muxer.Sample>) ,public void clear() ,public boolean equals(java.lang.Object) ,public abstract org.mp4parser.muxer.Sample get(int) ,public int hashCode() ,public int indexOf(java.lang.Object) ,public Iterator<org.mp4parser.muxer.Sample> iterator() ,public int lastIndexOf(java.lang.Object) ,public ListIterator<org.mp4parser.muxer.Sample> listIterator() ,public ListIterator<org.mp4parser.muxer.Sample> listIterator(int) ,public org.mp4parser.muxer.Sample remove(int) ,public org.mp4parser.muxer.Sample set(int, org.mp4parser.muxer.Sample) ,public List<org.mp4parser.muxer.Sample> subList(int, int) <variables>protected transient int modCount