I was wondering if it's possible to play a video using the Secure Reliable Transfer protocol. Videos of this type start with srt://
. I know that VideoView only supports https and another protocol I don't remember but not srt.
Any attempt at googling this yields results concerning srt subtitle files, which isn't what I am looking for.
Does anyone know how one might play an srt video on android?
If anyone comes here looking for an answer, here's what I did to get it working. My approach was for a live stream but it can be modified to work with single file type videos.
I managed to implement a custom ExoPlayer DataSource that works with live streaming SRT.
class SrtLiveStreamDataSourceFactory(
private val srtUrl: String,
private val port: Int,
private val passPhrase: String? = null
) :
DataSource.Factory {
override fun createDataSource(): DataSource {
return SrtLiveStreamDataSource(srtUrl, port, passPhrase)
}
}
const val PAYLOAD_SIZE = 1316
class SrtLiveStreamDataSource(
private val srtUrl: String,
private val port: Int,
private val passPhrase: String?
) :
BaseDataSource(/*isNetwork*/true) {
private var socket: Socket? = null
private val byteQueue: Queue<Byte> = LinkedList()
override fun open(dataSpec: DataSpec): Long {
socket = Socket()
socket?.setSockFlag(SockOpt.TRANSTYPE, Transtype.LIVE)
socket?.setSockFlag(SockOpt.PAYLOADSIZE, PAYLOAD_SIZE)
if(passPhrase != null){
socket?.setSockFlag(SockOpt.PASSPHRASE, passPhrase)
}
socket?.connect(srtUrl, port)
return C.LENGTH_UNSET.toLong()
}
/**
* Receives from SRT socket and feeds into a queue. Depending on the length requested
* from exoplayer, that amount of bytes is polled from queue and onto the buffer with the given offset.
*
* You cannot directly receive at the given length from the socket, because SRT uses a
* predetermined payload size that cannot be dynamic
*/
override fun read(buffer: ByteArray, offset: Int, length: Int): Int {
if (length == 0) {
return 0
}
var bytesReceived = 0
if (socket != null) {
val received = socket!!.recv(PAYLOAD_SIZE)
for (byte in received.second /*received byte array*/) {
byteQueue.offer(byte)
}
repeat(length) { index ->
val byte = byteQueue.poll()
if (byte != null) {
buffer[index + offset] = byte
bytesReceived++
}
}
return bytesReceived
}
throw IOException("Couldn't read bytes at offset: $offset")
}
override fun getUri(): Uri? {
return Uri.parse("srt://$srtUrl:$port")
}
override fun close() {
socket?.close()
socket = null
}
}
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val url = SRT_URL_HERE (exclude srt://)
val port = PORT_HERE
val source = ProgressiveMediaSource.Factory(
SrtLiveStreamDataSourceFactory(
url,
port,
),
).createMediaSource(MediaItem.fromUri(Uri.EMPTY))
val player = ExoPlayer.Builder(this)
.build()
player.setMediaSource(source)
binding.playerView.player = player
player.prepare()
player.play()
player.playWhenReady = true
}
}