Все кадры принимаются. Журналы: < /p>
Код: Выделить всё
EglRenderer: SurfaceVideoSinkDuration: 4001 ms. Frames received: 25. Dropped: 0. Rendered: 25. Render fps: 6.2. Average render time: 418 us. Average swapBuffer time: 7856 us.
< /code>
MainActivity.kt
Код: Выделить всё
@Preview(showBackground = true, showSystemUi = true)
@Composable
fun MainActivityPreview(roomId: String = "10086") {
val context = LocalContext.current
val host = "http://192.168.2.112:4000"
var mSurfaceView by remember { mutableStateOf(null) }
Column {
Text("Remote Preview")
var surfaceView by remember { mutableStateOf(null) }
AndroidView(
factory = { context ->
surfaceView = SurfaceView(context)
val holder = surfaceView!!.holder
holder.addCallback(object : SurfaceHolder.Callback {
override fun surfaceCreated(holder: SurfaceHolder) {
ThreadUtils.checkIsOnMainThread()
mSurfaceView = holder.surface
}
override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {}
override fun surfaceDestroyed(holder: SurfaceHolder) {}
})
surfaceView!!
},
modifier = Modifier.weight(1f)
)
Button(onClick = {
GlobalConstants.renderSurface = mSurfaceView
GlobalConstants.requireWebRTC(this@MainActivity)
}) {
Text("Connect")
}
Button(onClick = {
GlobalConstants.disconnectWebRTC()
}) {
Text("Disconnect")
}
}
}
< /code>
GlobalConstants.kt
Код: Выделить всё
var renderSurface: Surface? = null
var renderSink: VideoSink? = null
val eglBase = EglBase.create()
fun disconnectWebRTC() {
Log.d("PeerConnectionClient", "Require to disconnect from remote")
peerConnectionClient?.let {
it.onDestroy()
Log.d("PeerConnectionClient", "WebRTC disconnected")
peerConnectionClient = null
}
}
fun requireWebRTC(applicationContext: Context) {
disconnectWebRTC()
peerConnectionClient = PeerConnectionClient(
applicationContext,
"10086",
SimpleRtcListener(
fxOnAddRemoteStream = {
val mainHandler = Handler(Looper.getMainLooper())
mainHandler.post {
renderSink?.let { sink ->
it.videoTracks.first().addSink(sink)
}
if (renderSurface != null) {
Log.d("PeerConnectionClient", "Target Surface: $renderSurface")
it.videoTracks.first().addSink(
SurfaceVideoSink(
renderSurface!!,
eglBase.eglBaseContext
)
)
} else {
Log.w("PeerConnectionClient", "Target Surface not found")
}
}
}
),
"http://192.168.2.112:4000",
EglBase.create()
)
}
< /code>
SurfaceVideoSink.kt
Код: Выделить всё
class SurfaceVideoSink(
surface: Surface,
eglBaseContext: EglBase.Context
) : VideoSink {
private val eglRenderer: EglRenderer = EglRenderer("SurfaceVideoSink")
init {
Handler(Looper.getMainLooper()).post {
ThreadUtils.checkIsOnMainThread()
eglRenderer.init(
eglBaseContext,
EglBase.CONFIG_PLAIN,
GlRectDrawer()
)
eglRenderer.createEglSurface(surface)
}
eglRenderer.setMirror(false)
eglRenderer.disableFpsReduction()
}
override fun onFrame(frame: VideoFrame) {
try {
eglRenderer.onFrame(frame)
} catch (e: Exception) {
Log.e("SurfaceVideoSink", "Render error", e)
}
}
}
< /code>
Why does rendering to a custom Surface
Подробнее здесь: https://stackoverflow.com/questions/797 ... ewrenderer