Skip to content

Instantly share code, notes, and snippets.

@habibg1232191
Last active February 28, 2022 15:07
Show Gist options
  • Save habibg1232191/c3bcafb22ffcc17132c1a590f97e6b5c to your computer and use it in GitHub Desktop.
Save habibg1232191/c3bcafb22ffcc17132c1a590f97e6b5c to your computer and use it in GitHub Desktop.
import androidx.compose.foundation.Image
import androidx.compose.runtime.*
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.toComposeImageBitmap
import kotlinx.coroutines.delay
import org.bytedeco.ffmpeg.avcodec.AVCodecParameters
import org.bytedeco.ffmpeg.avutil.AVFrame
import org.bytedeco.ffmpeg.global.*
import org.bytedeco.ffmpeg.global.avformat.avformat_find_stream_info
import org.bytedeco.ffmpeg.global.avformat.avformat_open_input
import org.bytedeco.ffmpeg.global.avutil.*
import org.bytedeco.ffmpeg.global.swscale.sws_freeContext
import org.bytedeco.ffmpeg.swscale.SwsContext
import org.bytedeco.javacpp.BytePointer
import org.bytedeco.javacpp.DoublePointer
import org.bytedeco.javacpp.Loader
import org.bytedeco.javacpp.PointerPointer
import org.jetbrains.skia.*
import java.nio.Buffer
@Composable
fun MediaPlayer() {
val videoUrl by remember { mutableStateOf("<VideoUrl>") }
var imageBitmap by remember { mutableStateOf<ImageBitmap?>(null) }
LaunchedEffect(Unit) {
Loader.load(avutil::class.java)
Loader.load(swresample::class.java)
Loader.load(avcodec::class.java)
Loader.load(avformat::class.java)
Loader.load(swscale::class.java)
// Register all formats and codecs
avcodec.av_jni_set_java_vm(Loader.getJavaVM(), null)
avcodec.avcodec_register_all()
avformat.av_register_all()
avformat.avformat_network_init()
Loader.load(avdevice::class.java)
avdevice.avdevice_register_all()
val pFormatContext = avformat.avformat_alloc_context()
avformat_open_input(pFormatContext, videoUrl, null, null)
avformat_find_stream_info(pFormatContext, null as PointerPointer<*>?)
var pCodecParameters = AVCodecParameters(null)
var videoStream = -1
for (i in 0 until pFormatContext.nb_streams()) {
val pLocalCodecParameters = pFormatContext.streams(i).codecpar()
if(pLocalCodecParameters.codec_type() == AVMEDIA_TYPE_VIDEO) {
pCodecParameters = pLocalCodecParameters
videoStream = i
}
}
val pCodec = avcodec.avcodec_find_decoder(pCodecParameters.codec_id())
val pCodecContext = avcodec.avcodec_alloc_context3(pCodec)
avcodec.avcodec_parameters_to_context(pCodecContext, pCodecParameters)
avcodec.avcodec_open2(pCodecContext, pCodec, null as PointerPointer<*>?)
val pPacket = avcodec.av_packet_alloc()
val pFrame = av_frame_alloc()
val pFrameRgb = av_frame_alloc()
var imgConvertCtx: SwsContext
while(avformat.av_read_frame(pFormatContext, pPacket) >= 0) {
val err = avcodec.avcodec_send_packet(pCodecContext, pPacket)
val err2 = avcodec.avcodec_receive_frame(pCodecContext, pFrame)
if(pPacket.stream_index() == videoStream && err >= 0 && err2 >= 0) {
val fmt = pCodecContext.pix_fmt()
val info = ImageInfo.makeN32(pFrame.width(), pFrame.height(), ColorAlphaType.OPAQUE)
val bm = Bitmap()
bm.allocPixels(info, info.minRowBytes)
imgConvertCtx = swscale.sws_getContext(
pFrame.width(), pFrame.height(), pCodecContext.pix_fmt(),
info.width, info.height, fmt,
swscale.SWS_BILINEAR, null, null, null as DoublePointer?
)
// How can I write this in kotlin?
// uint8_t* dst[] = { (uint8_t*)bm.pixmap().writable_addr() };
// int dst_stride[] = { SkToInt(bm.pixmap().rowBytes()) };
swscale.sws_scale(
imgConvertCtx, pFrame.data(), pFrame.linesize(), 0,
pFrame.height(), PointerPointer<AVFrame?>(pFrameRgb), pFrameRgb.linesize()
)
sws_freeContext(imgConvertCtx)
bm.setImmutable()
imageBitmap = Image.makeFromBitmap(bm).toComposeImageBitmap()
println("Success decode frame")
delay(500)
}
}
}
imageBitmap?.let {
Image(
bitmap = it,
contentDescription = "Video"
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment