-
Notifications
You must be signed in to change notification settings - Fork 1
/
VlcjFrameController.kt
76 lines (65 loc) · 2.62 KB
/
VlcjFrameController.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
package vlcj
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import player.PlayerController
import player.frame.FrameRenderer
import uk.co.caprica.vlcj.player.embedded.videosurface.callback.BufferFormat
import uk.co.caprica.vlcj.player.embedded.videosurface.callback.BufferFormatCallback
import uk.co.caprica.vlcj.player.embedded.videosurface.callback.RenderCallback
import java.nio.ByteBuffer
class VlcjFrameController constructor(
private val controller: VlcjController = VlcjController(),
) : FrameRenderer, PlayerController by controller {
private fun getPixels(buffer: ByteBuffer, width: Int, height: Int) = runCatching {
buffer.rewind()
val pixels = ByteArray(width * height * 4)
for (y in 0 until height) {
for (x in 0 until width) {
val pixel = buffer.int
val index = (y * width + x) * 4
val b = (pixel and 0xff).toByte()
val g = (pixel shr 8 and 0xff).toByte()
val r = (pixel shr 16 and 0xff).toByte()
val a = (pixel shr 24 and 0xff).toByte()
pixels[index] = b
pixels[index + 1] = g
pixels[index + 2] = r
pixels[index + 3] = a
}
}
pixels
}.getOrNull()
private val bufferFormatCallback by lazy {
object : BufferFormatCallback {
override fun getBufferFormat(sourceWidth: Int, sourceHeight: Int) = BufferFormat(
"RV32",
sourceWidth,
sourceHeight,
intArrayOf(sourceWidth * 4),
intArrayOf(sourceHeight)
)
override fun allocatedBuffers(buffers: Array<out ByteBuffer>?) = Unit
}
}
private val renderCallback by lazy {
RenderCallback { _, nativeBuffers, bufferFormat ->
nativeBuffers?.firstOrNull()?.let { buffer ->
getPixels(buffer, bufferFormat.width, bufferFormat.height)?.let {
_size.value = bufferFormat.width to bufferFormat.height
_bytes.value = it
}
}
}
}
private val surface by lazy {
controller.factory.videoSurfaces().newVideoSurface(bufferFormatCallback, renderCallback, false)
}
private val _size = MutableStateFlow(0 to 0)
override val size = _size.asStateFlow()
private val _bytes = MutableStateFlow<ByteArray?>(null)
override val bytes = _bytes.asStateFlow()
override fun load(url: String) {
controller.load(url)
controller.player?.videoSurface()?.set(surface)
}
}