ThibaultBee / SrtPlayer

Android SRT player powered by Exoplayer and srtdroid
Apache License 2.0
17 stars 11 forks source link

Can’t use it in Media3. #3

Closed GreenVegetables closed 1 week ago

GreenVegetables commented 1 month ago

hello, I need your help.

my srt url is srt://192.168.3.42:1939?streamid=#!::r=live/0 It works fine in OBS Studio.

I want to use it in Media3.

code:

class SrtDataSource :
    BaseDataSource(/*isNetwork*/true) {

    companion object {
        private const val PAYLOAD_SIZE = 1316
        private const val TAG = "SrtDataSource"
    }

    private val byteQueue: Queue<ByteArray> = LinkedList()
    private var socket: SrtSocket? = null

    override fun open(dataSpec: DataSpec): Long {
        val streamId = dataSpec.uri.getQueryParameter("streamid")
        val passPhrase = dataSpec.uri.getQueryParameter("passphrase")
        val latency = dataSpec.uri.getQueryParameter("latency")

        socket = SrtSocket().apply {
            setSockFlag(SockOpt.TRANSTYPE, Transtype.LIVE)
            setSockFlag(SockOpt.PAYLOADSIZE, PAYLOAD_SIZE)
            latency?.let {
                setSockFlag(SockOpt.LATENCY, it.toInt())
            }
            passPhrase?.let {
                setSockFlag(SockOpt.PASSPHRASE, it)
            }
            streamId?.let {
                setSockFlag(SockOpt.STREAMID, it)
            }
            dataSpec.key?.let { setSockFlag(SockOpt.PASSPHRASE, it) }

            Log.i(TAG, "Connecting to ${dataSpec.uri.host}:${dataSpec.uri.port}.")
            dataSpec.uri.host?.let { connect(it, dataSpec.uri.port) }
                ?: throw IOException("Host is not valid")
        }
        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
        }

        socket?.let {
            var bytesReceived = 0
            /*val received = it.recv(PAYLOAD_SIZE)
            (0 until received.first / TS_PACKET_SIZE).forEach { i ->
                byteQueue.offer(
                    received.second.copyOfRange(
                        i * TS_PACKET_SIZE,
                        (i + 1) * TS_PACKET_SIZE
                    )
                )
            }*/
            val rcvBuffer = it.recv(PAYLOAD_SIZE)
            (0 until rcvBuffer.size / TS_PACKET_SIZE).forEach { i ->
                byteQueue.offer(
                    rcvBuffer.copyOfRange(
                        i * TS_PACKET_SIZE,
                        (i + 1) * TS_PACKET_SIZE
                    )
                )
            }

            var tmpBuffer = byteQueue.poll()
            var i = 0
            while (tmpBuffer != null) {
                System.arraycopy(tmpBuffer, 0, buffer, offset + i * TS_PACKET_SIZE, TS_PACKET_SIZE)
                bytesReceived += TS_PACKET_SIZE
                i++
                if (i * TS_PACKET_SIZE >= length) {
                    break
                }
                tmpBuffer = byteQueue.poll()
            }

            return bytesReceived
        }
        throw IOException("Couldn't read bytes at offset: $offset")
    }

    override fun getUri(): Uri {
        return Uri.parse("srt://")
    }

    override fun close() {
        byteQueue.clear()
        socket?.close()
        socket = null
    }
}

error log

Connecting to 192.168.3.42:1939.
com.google.android.exoplayer2.ExoPlaybackException: Source error
at com.google.android.exoplayer2.ExoPlayerImplInternal.handleIoException(ExoPlayerImplInternal.java:684)
at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:660)
at android.os.Handler.dispatchMessage(Handler.java:113)
at android.os.Looper.loopOnce(Looper.java:210)
at android.os.Looper.loop(Looper.java:302)
at android.os.HandlerThread.run(HandlerThread.java:67)
Caused by: java.net.SocketException: Connection was broken
at io.github.thibaultbee.srtdroid.core.models.SrtSocket.recv(SrtSocket.kt:839)
at io.github.thibaultbee.srtplayer.player.SrtDataSource.read(SrtDataSource.kt:77)
at com.google.android.exoplayer2.upstream.StatsDataSource.read(StatsDataSource.java:98)
at com.google.android.exoplayer2.extractor.DefaultExtractorInput.readFromUpstream(DefaultExtractorInput.java:299)
at com.google.android.exoplayer2.extractor.DefaultExtractorInput.read(DefaultExtractorInput.java:76)
at com.google.android.exoplayer2.extractor.ts.TsExtractor.fillBufferWithAtLeastOnePacket(TsExtractor.java:441)
at com.google.android.exoplayer2.extractor.ts.TsExtractor.read(TsExtractor.java:331)
at com.google.android.exoplayer2.source.BundledExtractorsAdapter.read(BundledExtractorsAdapter.java:133)
at com.google.android.exoplayer2.source.ProgressiveMediaPeriod$ExtractingLoadable.load(ProgressiveMediaPeriod.java:1047)
at com.google.android.exoplayer2.upstream.Loader$LoadTask.run(Loader.java:420)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)
at java.lang.Thread.run(Thread.java:1019)
ThibaultBee commented 1 month ago

Hi, So, what is your question? I don't do support of SrtPlayer, you got to debug it on your own.

GreenVegetables commented 1 month ago

Got it. My issue is that the SRT stream isn’t playing correctly. I think it might be because the stream ID isn’t being extracted from the URI properly, but I’m not sure. I’ll try to figure it out on my own.

ThibaultBee commented 1 month ago

But you are right, the streamid syntax is not parsed properly. I will have to develop an encoder/decoder for stream id format (see https://github.com/Haivision/srt/blob/master/docs/features/access-control.md?plain=1) in few weeks for srtdroid. If you find something to parse it with Uri, could you share it please?

GreenVegetables commented 1 month ago

That’s good news! I tried URL encoding the streamid, and it shows up correctly, like this: srt://192.168.3.42:1939?streamid=%23!%3A%3Ar%3Dlive%2F0%2Cm%3Dpublish. But it’s still not playing properly. I’m not sure if there’s something else that’s causing the problem. By the way, I found some info about streamid that might help: https://github.com/Haivision/srt/issues/1871.

ThibaultBee commented 2 weeks ago

Could you test on the main branch?

! syntax is not compatible with Uri standard.

ThibaultBee commented 1 week ago

Stalled issue. Closing.