You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
78 lines
3.0 KiB
78 lines
3.0 KiB
package org.jetbrains.compose.videoplayer |
|
|
|
import androidx.compose.runtime.State |
|
import androidx.compose.runtime.mutableStateOf |
|
import androidx.compose.ui.graphics.ImageBitmap |
|
import androidx.compose.ui.graphics.asComposeImageBitmap |
|
import org.jetbrains.skia.Bitmap |
|
import org.jetbrains.skia.ColorAlphaType |
|
import org.jetbrains.skia.ColorType |
|
import org.jetbrains.skia.ImageInfo |
|
import uk.co.caprica.vlcj.player.base.MediaPlayer |
|
import uk.co.caprica.vlcj.player.embedded.videosurface.CallbackVideoSurface |
|
import uk.co.caprica.vlcj.player.embedded.videosurface.VideoSurface |
|
import uk.co.caprica.vlcj.player.embedded.videosurface.VideoSurfaceAdapters |
|
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 uk.co.caprica.vlcj.player.embedded.videosurface.callback.format.RV32BufferFormat |
|
import java.nio.ByteBuffer |
|
import javax.swing.SwingUtilities |
|
|
|
internal class SkiaBitmapVideoSurface : VideoSurface(VideoSurfaceAdapters.getVideoSurfaceAdapter()) { |
|
|
|
private val videoSurface = SkiaBitmapVideoSurface() |
|
private lateinit var imageInfo: ImageInfo |
|
private lateinit var frameBytes: ByteArray |
|
private val skiaBitmap: Bitmap = Bitmap() |
|
private val composeBitmap = mutableStateOf<ImageBitmap?>(null) |
|
|
|
val bitmap: State<ImageBitmap?> = composeBitmap |
|
|
|
override fun attach(mediaPlayer: MediaPlayer) { |
|
videoSurface.attach(mediaPlayer) |
|
} |
|
|
|
private inner class SkiaBitmapBufferFormatCallback : BufferFormatCallback { |
|
private var sourceWidth: Int = 0 |
|
private var sourceHeight: Int = 0 |
|
|
|
override fun getBufferFormat(sourceWidth: Int, sourceHeight: Int): BufferFormat { |
|
this.sourceWidth = sourceWidth |
|
this.sourceHeight = sourceHeight |
|
return RV32BufferFormat(sourceWidth, sourceHeight) |
|
} |
|
|
|
override fun allocatedBuffers(buffers: Array<ByteBuffer>) { |
|
frameBytes = buffers[0].run { ByteArray(remaining()).also(::get) } |
|
imageInfo = ImageInfo( |
|
sourceWidth, |
|
sourceHeight, |
|
ColorType.BGRA_8888, |
|
ColorAlphaType.PREMUL, |
|
) |
|
} |
|
} |
|
|
|
private inner class SkiaBitmapRenderCallback : RenderCallback { |
|
override fun display( |
|
mediaPlayer: MediaPlayer, |
|
nativeBuffers: Array<ByteBuffer>, |
|
bufferFormat: BufferFormat, |
|
) { |
|
SwingUtilities.invokeLater { |
|
nativeBuffers[0].rewind() |
|
nativeBuffers[0].get(frameBytes) |
|
skiaBitmap.installPixels(imageInfo, frameBytes, bufferFormat.width * 4) |
|
composeBitmap.value = skiaBitmap.asComposeImageBitmap() |
|
} |
|
} |
|
} |
|
|
|
private inner class SkiaBitmapVideoSurface : CallbackVideoSurface( |
|
SkiaBitmapBufferFormatCallback(), |
|
SkiaBitmapRenderCallback(), |
|
true, |
|
videoSurfaceAdapter, |
|
) |
|
}
|
|
|