Saltar al contenido

Reproducción de video encriptado usando ExoPlayer

Hacemos una revisión completa cada una de las reseñas de nuestro espacio con el objetivo de mostrarte siempre la información certera y actual.

Solución:

Ejemplo de cómo reproducir un archivo de audio encriptado, espero que esto ayude a alguien. Estoy usando Kotlin aquí

import android.net.Uri
import com.google.android.exoplayer2.C
import com.google.android.exoplayer2.upstream.DataSource
import com.google.android.exoplayer2.upstream.DataSourceInputStream
import com.google.android.exoplayer2.upstream.DataSpec
import com.google.android.exoplayer2.util.Assertions
import java.io.IOException
import javax.crypto.CipherInputStream

class EncryptedDataSource(upstream: DataSource) : DataSource 

    private var upstream: DataSource? = upstream
    private var cipherInputStream: CipherInputStream? = null

    override fun open(dataSpec: DataSpec?): Long 
        val cipher = getCipherInitDecrypt()
        val inputStream = DataSourceInputStream(upstream, dataSpec)
        cipherInputStream = CipherInputStream(inputStream, cipher)
        inputStream.open()
        return C.LENGTH_UNSET.toLong()

    

    override fun read(buffer: ByteArray?, offset: Int, readLength: Int): Int 
        Assertions.checkNotNull(cipherInputStream)
        val bytesRead = cipherInputStream!!.read(buffer, offset, readLength)
        return if (bytesRead < 0) 
            C.RESULT_END_OF_INPUT
         else bytesRead
    

    override fun getUri(): Uri 
        return upstream!!.uri
    

    @Throws(IOException::class)
    override fun close() 
        if (cipherInputStream != null) 
            cipherInputStream = null
            upstream!!.close()
        
    

En la función anterior, debe obtener Cipher que se usó para el cifrado y iniciarlo: algo como esto

fun getCipherInitDecrypt(): Cipher 
    val cipher = Cipher.getInstance("AES/CTR/NoPadding", "BC");
    val iv = IvParameterSpec(initVector.toByteArray(charset("UTF-8")))
    val skeySpec = SecretKeySpec(key, TYPE_RSA)
    cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv)
    return cipher

El siguiente paso es crear DataSource.Factory por DataSource hemos implementado antes

import com.google.android.exoplayer2.upstream.DataSource

class EncryptedFileDataSourceFactory(var dataSource: DataSource) : DataSource.Factory 

    override fun createDataSource(): DataSource 
        return EncryptedDataSource(dataSource)
    

Y el último paso es la inicialización de los jugadores.

    private fun prepareExoPlayerFromFileUri(uri: Uri) 
        val player = ExoPlayerFactory.newSimpleInstance(
                    DefaultRenderersFactory(this),
                    DefaultTrackSelector(),
                    DefaultLoadControl())

        val playerView = findViewById(R.id.player_view)
        playerView.player = player

        val dsf = DefaultDataSourceFactory(this, Util.getUserAgent(this, "ExoPlayerInfo"))
        //This line do the thing
        val mediaSource = ExtractorMediaSource.Factory(EncryptedFileDataSourceFactory(dsf.createDataSource())).createMediaSource(uri)
        player.prepare(mediaSource)
    

Finalmente encontré la solución.

Usé un no-padding para el algoritmo de cifrado, de esta manera:

cipher = Cipher.getInstance("AES/CTR/NoPadding", "BC");

para que el tamaño del archivo cifrado y el tamaño del archivo claro permanezcan iguales. Entonces ahora creé la secuencia:

cipherInputStream = new CipherInputStream(inputStream, cipher) 
    @Override
    public int available() throws IOException 
         return in.available();
    
;

Esto se debe a que la documentación de Java dice sobre ChiperInputStream.available() ese

Este método deberían ser anulado

y en realidad creo que es más como un MUST, porque los valores recuperados de ese método son a menudo realmente extraños.

¡Y eso es todo! Ahora funciona perfectamente.

No creo que una fuente de datos personalizada, con abrir / leer / cerrar, sea una solución para sus necesidades. Para un descifrado 'sobre la marcha' (valioso para archivos grandes, pero no solo), debe diseñar una arquitectura de transmisión.

Ya hay publicaciones similares a las tuyas. Para encontrarlos, no busque 'exoplayer', sino 'videoview' o 'mediaplayer'. Las respuestas deben ser compatibles.

Por ejemplo, reproducir archivos de video encriptados usando VideoView

Acuérdate de que tienes autorización de parafrasear tu experiencia si te fue preciso.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *