Reproducing encrypted video using ExoPlayer

前端 未结 5 1921
心在旅途
心在旅途 2020-12-07 22:51

I\'m using ExoPlayer, in Android, and I\'m trying to reproduce an encrypted video stored locally.

The modularity of ExoPlayer allows to create custom components tha

5条回答
  •  无人及你
    2020-12-07 23:55

    Example how to play encrypted audio file, hope this will help to someone. I'm using Kotlin here

    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()
            }
        }
    }
    

    In function above you need to get Cipher which was used for encryption and init it: smth like this

    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
    }
    

    Next step is creating DataSource.Factory for DataSource we've implemented earlier

    import com.google.android.exoplayer2.upstream.DataSource
    
    class EncryptedFileDataSourceFactory(var dataSource: DataSource) : DataSource.Factory {
    
        override fun createDataSource(): DataSource {
            return EncryptedDataSource(dataSource)
        }
    }
    

    And last step is players initialization

        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)
        }
    

提交回复
热议问题