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