Verschlüsseltes Video mit ExoPlayer wiedergeben

Ich benutze ExoPlayer, in Android, und ich versuche, ein verschlüsseltes Video zu reproduzieren, das lokal gespeichert ist.

Die Modularität von ExoPlayer ermöglicht es, benutzerdefinierte Komponenten zu erstellen, die in den ExoPlayer injiziert werden können. Dies scheint der Fall zu sein. Nach einigen Recherchen wurde mir klar, dass ich zum Erreichen dieser Aufgabe eine benutzerdefinierte DataSource erstellen und @ überschreiben kanopen(), read() undclose().

Ich habe auch @ gefunddiese Lösun, aber eigentlich wird hier die gesamte Datei in einem Schritt entschlüsselt und in einem übersichtlichen Inputstream gespeichert. Dies kann in vielen Situationen gut sein. Aber was ist, wenn ich eine große Datei reproduzieren muss?

Die Frage ist also: Wie kann ich verschlüsselte Videos in ExoPlayer wiedergeben und Inhalte "on-fly" entschlüsseln (ohne die gesamte Datei zu entschlüsseln)? Ist das möglich?

Ich habe versucht, eine benutzerdefinierte DataSource mit der Methode open () zu erstellen:

@Override
    public long open(DataSpec dataSpec) throws FileDataSourceException {
        try {
            File file = new File(dataSpec.uri.getPath());

            clearInputStream = new CipherInputStream(new FileInputStream(file), mCipher);

            long skipped = clearInputStream.skip(dataSpec.position);
            if (skipped < dataSpec.position) {
                throw new EOFException();
            }
            if (dataSpec.length != C.LENGTH_UNBOUNDED) {
                bytesRemaining = dataSpec.length;
            } else {
                bytesRemaining = clearInputStream.available();
                if (bytesRemaining == 0) {
                    bytesRemaining = C.LENGTH_UNBOUNDED;
                }
            }
        } catch (EOFException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        opened = true;
        if (listener != null) {
            listener.onTransferStart();
        }

        return bytesRemaining;
    }

Und dies ist die Methode read ():

@Override
public int read(byte[] buffer, int offset, int readLength) throws FileDataSourceException {
        if (bytesRemaining == 0) {
            return -1;
        } else {
            int bytesRead = 0;

                int bytesToRead = bytesRemaining == C.LENGTH_UNBOUNDED ? readLength
                        : (int) Math.min(bytesRemaining, readLength);
            try {
                bytesRead = clearInputStream.read(buffer, offset, bytesToRead);
            } catch (IOException e) {
                e.printStackTrace();
            }

            if (bytesRead > 0) {
                if (bytesRemaining != C.LENGTH_UNBOUNDED) {
                    bytesRemaining -= bytesRead;
                }
                if (listener != null) {
                    listener.onBytesTransferred(bytesRead);
                }
            }

            return bytesRead;
        }
    }

Wenn ich anstelle einer verschlüsselten Datei eine klare Datei übergebe und nur den CipherInputStream-Teil entferne, funktioniert dies einwandfrei. Bei einer verschlüsselten Datei erhalte ich stattdessen den folgenden Fehler:

    Unexpected exception loading stream
java.lang.IllegalStateException: Top bit not zero: -1195853062
at com.google.android.exoplayer.util.ParsableByteArray.readUnsignedIntToInt(ParsableByteArray.java:240)
at com.google.android.exoplayer.extractor.mp4.Mp4Extractor.readSample(Mp4Extractor.java:331)
at com.google.android.exoplayer.extractor.mp4.Mp4Extractor.read(Mp4Extractor.java:122)
at com.google.android.exoplayer.extractor.ExtractorSampleSource$ExtractingLoadable.load(ExtractorSampleSource.java:745)
at com.google.android.exoplayer.upstream.Loader$LoadTask.run(Loader.java:209)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:423)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)

BEARBEITE:

das verschlüsselte Video wird auf folgende Weise generiert:

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec keySpec = new SecretKeySpec("0123456789012345".getBytes(), "AES");
IvParameterSpec ivSpec = new IvParameterSpec("0123459876543210".getBytes());
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);

outputStream = new CipherOutputStream(output_stream, cipher);

Dann wird der outputStream in einer Datei gespeichert.

Antworten auf die Frage(8)

Ihre Antwort auf die Frage